From d665eb6114c91f433473d4af8ff4e87e021b3ad8 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 22 Feb 2017 16:21:45 +0800 Subject: gpio: Add Rapid GPIO2P driver for i.MX7ULP Add the imx_rgpio2p driver for Rapid GPIO2P controllers on i.MX7ULP. Have added all ports on RGPIO2P_0 and RGPIO2P_1. The configurations CONFIG_IMX_RGPIO2P and CONFIG_DM_GPIO must be set to y to enable the drivers. To use the GPIO function, the IBE and OBE needs to set in IOMUXC. We did not set the bits in driver, but leave them to IOMUXC settings of the GPIO pins. User should use IMX_GPIO_NR to generate the GPIO number for gpio APIs access. Signed-off-by: Peng Fan Signed-off-by: Ye Li Reviewed-by : Stefano Babic --- drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 1 + drivers/gpio/imx_rgpio2p.c | 224 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 232 insertions(+) create mode 100644 drivers/gpio/imx_rgpio2p.c (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8d9ab5237e8..dc4108f378f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -48,6 +48,13 @@ config INTEL_BROADWELL_GPIO driver from the common Intel ICH6 driver. It supports a total of 95 GPIOs which can be configured from the device tree. +config IMX_RGPIO2P + bool "i.MX7ULP RGPIO2P driver" + depends on DM + default n + help + This driver supports i.MX7ULP Rapid GPIO2P controller. + config LPC32XX_GPIO bool "LPC32XX GPIO driver" depends on DM diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 89392264a4a..27f8068e3e6 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o obj-$(CONFIG_HIKEY_GPIO) += hi6220_gpio.o +obj-$(CONFIG_IMX_RGPIO2P) += imx_rgpio2p.o obj-$(CONFIG_PIC32_GPIO) += pic32_gpio.o obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o obj-$(CONFIG_MSM_GPIO) += msm_gpio.o diff --git a/drivers/gpio/imx_rgpio2p.c b/drivers/gpio/imx_rgpio2p.c new file mode 100644 index 00000000000..886b16188e8 --- /dev/null +++ b/drivers/gpio/imx_rgpio2p.c @@ -0,0 +1,224 @@ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * + * RGPIO2P driver for the Freescale i.MX7ULP. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +enum imx_rgpio2p_direction { + IMX_RGPIO2P_DIRECTION_IN, + IMX_RGPIO2P_DIRECTION_OUT, +}; + +#define GPIO_PER_BANK 32 + +struct imx_rgpio2p_data { + struct gpio_regs *regs; +}; + +struct imx_rgpio2p_plat { + int bank_index; + struct gpio_regs *regs; +}; + +static int imx_rgpio2p_is_output(struct gpio_regs *regs, int offset) +{ + u32 val; + + val = readl(®s->gpio_pddr); + + return val & (1 << offset) ? 1 : 0; +} + +static void imx_rgpio2p_bank_direction(struct gpio_regs *regs, int offset, + enum imx_rgpio2p_direction direction) +{ + u32 l; + + l = readl(®s->gpio_pddr); + + switch (direction) { + case IMX_RGPIO2P_DIRECTION_OUT: + l |= 1 << offset; + break; + case IMX_RGPIO2P_DIRECTION_IN: + l &= ~(1 << offset); + } + writel(l, ®s->gpio_pddr); +} + +static void imx_rgpio2p_bank_set_value(struct gpio_regs *regs, int offset, + int value) +{ + if (value) + writel((1 << offset), ®s->gpio_psor); + else + writel((1 << offset), ®s->gpio_pcor); +} + +static int imx_rgpio2p_bank_get_value(struct gpio_regs *regs, int offset) +{ + return (readl(®s->gpio_pdir) >> offset) & 0x01; +} + +static int imx_rgpio2p_direction_input(struct udevice *dev, unsigned offset) +{ + struct imx_rgpio2p_data *bank = dev_get_priv(dev); + + /* Configure GPIO direction as input. */ + imx_rgpio2p_bank_direction(bank->regs, offset, IMX_RGPIO2P_DIRECTION_IN); + + return 0; +} + +static int imx_rgpio2p_direction_output(struct udevice *dev, unsigned offset, + int value) +{ + struct imx_rgpio2p_data *bank = dev_get_priv(dev); + + /* Configure GPIO output value. */ + imx_rgpio2p_bank_set_value(bank->regs, offset, value); + + /* Configure GPIO direction as output. */ + imx_rgpio2p_bank_direction(bank->regs, offset, IMX_RGPIO2P_DIRECTION_OUT); + + return 0; +} + +static int imx_rgpio2p_get_value(struct udevice *dev, unsigned offset) +{ + struct imx_rgpio2p_data *bank = dev_get_priv(dev); + + return imx_rgpio2p_bank_get_value(bank->regs, offset); +} + +static int imx_rgpio2p_set_value(struct udevice *dev, unsigned offset, + int value) +{ + struct imx_rgpio2p_data *bank = dev_get_priv(dev); + + imx_rgpio2p_bank_set_value(bank->regs, offset, value); + + return 0; +} + +static int imx_rgpio2p_get_function(struct udevice *dev, unsigned offset) +{ + struct imx_rgpio2p_data *bank = dev_get_priv(dev); + + /* GPIOF_FUNC is not implemented yet */ + if (imx_rgpio2p_is_output(bank->regs, offset)) + return GPIOF_OUTPUT; + else + return GPIOF_INPUT; +} + +static const struct dm_gpio_ops imx_rgpio2p_ops = { + .direction_input = imx_rgpio2p_direction_input, + .direction_output = imx_rgpio2p_direction_output, + .get_value = imx_rgpio2p_get_value, + .set_value = imx_rgpio2p_set_value, + .get_function = imx_rgpio2p_get_function, +}; + +static int imx_rgpio2p_probe(struct udevice *dev) +{ + struct imx_rgpio2p_data *bank = dev_get_priv(dev); + struct imx_rgpio2p_plat *plat = dev_get_platdata(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + int banknum; + char name[18], *str; + + banknum = plat->bank_index; + sprintf(name, "GPIO%d_", banknum + 1); + str = strdup(name); + if (!str) + return -ENOMEM; + uc_priv->bank_name = str; + uc_priv->gpio_count = GPIO_PER_BANK; + bank->regs = plat->regs; + + return 0; +} + +static int imx_rgpio2p_bind(struct udevice *dev) +{ + struct imx_rgpio2p_plat *plat = dev->platdata; + fdt_addr_t addr; + + /* + * If platdata already exsits, directly return. + * Actually only when DT is not supported, platdata + * is statically initialized in U_BOOT_DEVICES.Here + * will return. + */ + if (plat) + return 0; + + addr = dev_get_addr_index(dev, 1); + if (addr == FDT_ADDR_T_NONE) + return -ENODEV; + + /* + * TODO: + * When every board is converted to driver model and DT is supported, + * this can be done by auto-alloc feature, but not using calloc + * to alloc memory for platdata. + */ + plat = calloc(1, sizeof(*plat)); + if (!plat) + return -ENOMEM; + + plat->regs = (struct gpio_regs *)addr; + plat->bank_index = dev->req_seq; + dev->platdata = plat; + + return 0; +} + + +static const struct udevice_id imx_rgpio2p_ids[] = { + { .compatible = "fsl,imx7ulp-gpio" }, + { } +}; + +U_BOOT_DRIVER(imx_rgpio2p) = { + .name = "imx_rgpio2p", + .id = UCLASS_GPIO, + .ops = &imx_rgpio2p_ops, + .probe = imx_rgpio2p_probe, + .priv_auto_alloc_size = sizeof(struct imx_rgpio2p_plat), + .of_match = imx_rgpio2p_ids, + .bind = imx_rgpio2p_bind, +}; + +#if !CONFIG_IS_ENABLED(OF_CONTROL) +static const struct imx_rgpio2p_plat imx_plat[] = { + { 0, (struct gpio_regs *)RGPIO2P_GPIO1_BASE_ADDR }, + { 1, (struct gpio_regs *)RGPIO2P_GPIO2_BASE_ADDR }, + { 2, (struct gpio_regs *)RGPIO2P_GPIO3_BASE_ADDR }, + { 3, (struct gpio_regs *)RGPIO2P_GPIO4_BASE_ADDR }, + { 4, (struct gpio_regs *)RGPIO2P_GPIO5_BASE_ADDR }, + { 5, (struct gpio_regs *)RGPIO2P_GPIO6_BASE_ADDR }, +}; + +U_BOOT_DEVICES(imx_rgpio2ps) = { + { "imx_rgpio2p", &imx_plat[0] }, + { "imx_rgpio2p", &imx_plat[1] }, + { "imx_rgpio2p", &imx_plat[2] }, + { "imx_rgpio2p", &imx_plat[3] }, + { "imx_rgpio2p", &imx_plat[4] }, + { "imx_rgpio2p", &imx_plat[5] }, +}; +#endif -- cgit v1.3.1 From 3ca0f0d2daabc763df0cedaf74b5049337aa4311 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 22 Feb 2017 16:21:46 +0800 Subject: mxc_ocotp: Update driver to support OCOTP controller on i.MX7ULP Update the mxc_ocotp driver to support i.MX7ULP. The read/write sequence has some changes due to PDN and OUT_STATUS registers added and TIME register is removed. Also update the bank size and number. Add is_mx7ulp macro in sys_proto.h Signed-off-by: Peng Fan Signed-off-by: Ye Li Reviewed-by : Stefano Babic --- arch/arm/include/asm/imx-common/sys_proto.h | 2 ++ drivers/misc/mxc_ocotp.c | 52 ++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/arch/arm/include/asm/imx-common/sys_proto.h b/arch/arm/include/asm/imx-common/sys_proto.h index 539d34bbdd9..732b6922dee 100644 --- a/arch/arm/include/asm/imx-common/sys_proto.h +++ b/arch/arm/include/asm/imx-common/sys_proto.h @@ -38,6 +38,8 @@ #define is_mx6ull() (is_cpu_type(MXC_CPU_MX6ULL)) #define is_mx6sll() (is_cpu_type(MXC_CPU_MX6SLL)) +#define is_mx7ulp() (is_cpu_type(MXC_CPU_MX7ULP)) + u32 get_nr_cpus(void); u32 get_cpu_rev(void); u32 get_cpu_speed_grade_hz(void); diff --git a/drivers/misc/mxc_ocotp.c b/drivers/misc/mxc_ocotp.c index 0b1c05078f3..88610d6af2c 100644 --- a/drivers/misc/mxc_ocotp.c +++ b/drivers/misc/mxc_ocotp.c @@ -29,6 +29,12 @@ #ifdef CONFIG_MX7 #define BM_CTRL_ADDR 0x0000000f #define BM_CTRL_RELOAD 0x00000400 +#elif defined(CONFIG_MX7ULP) +#define BM_CTRL_ADDR 0x000000FF +#define BM_CTRL_RELOAD 0x00000400 +#define BM_OUT_STATUS_DED 0x00000400 +#define BM_OUT_STATUS_LOCKED 0x00000800 +#define BM_OUT_STATUS_PROGFAIL 0x00001000 #else #define BM_CTRL_ADDR 0x0000007f #endif @@ -70,6 +76,9 @@ #elif defined CONFIG_MX7 #define FUSE_BANK_SIZE 0x40 #define FUSE_BANKS 16 +#elif defined(CONFIG_MX7ULP) +#define FUSE_BANK_SIZE 0x80 +#define FUSE_BANKS 31 #else #error "Unsupported architecture\n" #endif @@ -98,7 +107,7 @@ u32 fuse_bank_physical(int index) { u32 phy_index; - if (is_mx6sl()) { + if (is_mx6sl() || is_mx7ulp()) { phy_index = index; } else if (is_mx6ul() || is_mx6ull() || is_mx6sll()) { if ((is_mx6ull() || is_mx6sll()) && index == 8) @@ -187,6 +196,10 @@ static int finish_access(struct ocotp_regs *regs, const char *caller) err = !!(readl(®s->ctrl) & BM_CTRL_ERROR); clear_error(regs); +#ifdef CONFIG_MX7ULP + /* Need to power down the OTP memory */ + writel(1, ®s->pdn); +#endif if (err) { printf("mxc_ocotp %s(): Access protect error\n", caller); return -EIO; @@ -217,6 +230,13 @@ int fuse_read(u32 bank, u32 word, u32 *val) *val = readl(®s->bank[phy_bank].fuse_regs[phy_word << 2]); +#ifdef CONFIG_MX7ULP + if (readl(®s->out_status) & BM_OUT_STATUS_DED) { + writel(BM_OUT_STATUS_DED, ®s->out_status_clr); + printf("mxc_ocotp %s(): fuse read wrong\n", __func__); + return -EIO; + } +#endif return finish_access(regs, __func__); } @@ -238,6 +258,12 @@ static void set_timing(struct ocotp_regs *regs) clrsetbits_le32(®s->timing, BM_TIMING_FSOURCE | BM_TIMING_PROG, timing); } +#elif defined(CONFIG_MX7ULP) +static void set_timing(struct ocotp_regs *regs) +{ + /* No timing set for MX7ULP */ +} + #else static void set_timing(struct ocotp_regs *regs) { @@ -302,6 +328,14 @@ int fuse_sense(u32 bank, u32 word, u32 *val) *val = readl(®s->read_fuse_data); #endif +#ifdef CONFIG_MX7ULP + if (readl(®s->out_status) & BM_OUT_STATUS_DED) { + writel(BM_OUT_STATUS_DED, ®s->out_status_clr); + printf("mxc_ocotp %s(): fuse read wrong\n", __func__); + return -EIO; + } +#endif + return finish_access(regs, __func__); } @@ -355,6 +389,14 @@ int fuse_prog(u32 bank, u32 word, u32 val) #endif udelay(WRITE_POSTAMBLE_US); +#ifdef CONFIG_MX7ULP + if (readl(®s->out_status) & (BM_OUT_STATUS_PROGFAIL | BM_OUT_STATUS_LOCKED)) { + writel((BM_OUT_STATUS_PROGFAIL | BM_OUT_STATUS_LOCKED), ®s->out_status_clr); + printf("mxc_ocotp %s(): fuse write is failed\n", __func__); + return -EIO; + } +#endif + return finish_access(regs, __func__); } @@ -374,5 +416,13 @@ int fuse_override(u32 bank, u32 word, u32 val) writel(val, ®s->bank[phy_bank].fuse_regs[phy_word << 2]); +#ifdef CONFIG_MX7ULP + if (readl(®s->out_status) & (BM_OUT_STATUS_PROGFAIL | BM_OUT_STATUS_LOCKED)) { + writel((BM_OUT_STATUS_PROGFAIL | BM_OUT_STATUS_LOCKED), ®s->out_status_clr); + printf("mxc_ocotp %s(): fuse write is failed\n", __func__); + return -EIO; + } +#endif + return finish_access(regs, __func__); } -- cgit v1.3.1 From 253531bbd9cd2fe39359962bfb4338970bf56185 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Wed, 22 Feb 2017 16:21:48 +0800 Subject: wdog: Add the watchdog driver for MX7ULP. This driver implements the HW WATCHDOG functions. Which needs to set CONFIG_HW_WATCHDOG to use them. This is disabled by default for mx7ulp. Use watchdog for reset cpu. Implement this in the driver. Need to define CONFIG_ULP_WATCHDOG to build it. Signed-off-by: Peng Fan Signed-off-by: Ye Li Cc: Stefano Babic --- drivers/watchdog/Kconfig | 8 ++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/ulp_wdog.c | 98 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 drivers/watchdog/ulp_wdog.c (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index e69de29bb2d..dbdaafc1498 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -0,0 +1,8 @@ +menu "WATCHDOG support" + +config ULP_WATCHDOG + bool "i.MX7ULP watchdog" + help + Say Y here to enable i.MX7ULP watchdog driver. + +endmenu diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index a007ae82340..dea18363caa 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o obj-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o +obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o diff --git a/drivers/watchdog/ulp_wdog.c b/drivers/watchdog/ulp_wdog.c new file mode 100644 index 00000000000..72ec694cdd4 --- /dev/null +++ b/drivers/watchdog/ulp_wdog.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +/* + * MX7ULP WDOG Register Map + */ +struct wdog_regs { + u8 cs1; + u8 cs2; + u16 reserve0; + u32 cnt; + u32 toval; + u32 win; +}; + +#ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS +#define CONFIG_WATCHDOG_TIMEOUT_MSECS 0x1500 +#endif + +#define REFRESH_WORD0 0xA602 /* 1st refresh word */ +#define REFRESH_WORD1 0xB480 /* 2nd refresh word */ + +#define UNLOCK_WORD0 0xC520 /* 1st unlock word */ +#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */ + +#define WDGCS1_WDGE (1<<7) +#define WDGCS1_WDGUPDATE (1<<5) + +#define WDGCS2_FLG (1<<6) + +#define WDG_BUS_CLK (0x0) +#define WDG_LPO_CLK (0x1) +#define WDG_32KHZ_CLK (0x2) +#define WDG_EXT_CLK (0x3) + +DECLARE_GLOBAL_DATA_PTR; + +void hw_watchdog_set_timeout(u16 val) +{ + /* setting timeout value */ + struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; + + writel(val, &wdog->toval); +} + +void hw_watchdog_reset(void) +{ + struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; + + writel(REFRESH_WORD0, &wdog->cnt); + writel(REFRESH_WORD1, &wdog->cnt); +} + +void hw_watchdog_init(void) +{ + u8 val; + struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; + + writel(UNLOCK_WORD0, &wdog->cnt); + writel(UNLOCK_WORD1, &wdog->cnt); + + val = readb(&wdog->cs2); + val |= WDGCS2_FLG; + writeb(val, &wdog->cs2); + + hw_watchdog_set_timeout(CONFIG_WATCHDOG_TIMEOUT_MSECS); + writel(0, &wdog->win); + + writeb(WDG_LPO_CLK, &wdog->cs2);/* setting 1-kHz clock source */ + writeb((WDGCS1_WDGE | WDGCS1_WDGUPDATE), &wdog->cs1);/* enable counter running */ + + hw_watchdog_reset(); +} + +void reset_cpu(ulong addr) +{ + struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; + + writel(UNLOCK_WORD0, &wdog->cnt); + writel(UNLOCK_WORD1, &wdog->cnt); + + hw_watchdog_set_timeout(5); /* 5ms timeout */ + writel(0, &wdog->win); + + writeb(WDG_LPO_CLK, &wdog->cs2);/* setting 1-kHz clock source */ + writeb(WDGCS1_WDGE, &wdog->cs1);/* enable counter running */ + + hw_watchdog_reset(); + + while (1); +} -- cgit v1.3.1 From 4aa9d4d09523679ee9463cfade86de2bbf860273 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 22 Feb 2017 16:21:49 +0800 Subject: pinctrl: Add i.MX7ULP pinctrl driver Add i.MX7ULP pinctrl driver. Select CONFIG_PINCTRL_IMX7ULP to use this driver. Signed-off-by: Peng Fan Reviewed-by: Simon Glass Reviewed-by : Stefano Babic --- drivers/pinctrl/nxp/Kconfig | 14 ++++++++++++ drivers/pinctrl/nxp/Makefile | 1 + drivers/pinctrl/nxp/pinctrl-imx.c | 10 +++++---- drivers/pinctrl/nxp/pinctrl-imx.h | 3 +++ drivers/pinctrl/nxp/pinctrl-imx7ulp.c | 41 +++++++++++++++++++++++++++++++++++ 5 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 drivers/pinctrl/nxp/pinctrl-imx7ulp.c (limited to 'drivers') diff --git a/drivers/pinctrl/nxp/Kconfig b/drivers/pinctrl/nxp/Kconfig index 238f77d03ef..b668359a0bf 100644 --- a/drivers/pinctrl/nxp/Kconfig +++ b/drivers/pinctrl/nxp/Kconfig @@ -42,3 +42,17 @@ config PINCTRL_IMX7 configuration. This driver is different from the linux one, this is a simple implementation, only parses the 'fsl,pins' property and configure related registers. + +config PINCTRL_IMX7ULP + bool "IMX7ULP pinctrl driver" + depends on ARCH_MX7ULP && PINCTRL_FULL + select DEVRES + select PINCTRL_IMX + help + Say Y here to enable the imx7ulp pinctrl driver + + This provides a simple pinctrl driver for i.MX7ULP SoC familiy. + This feature depends on device tree configuration. This driver + is different from the linux one, this is a simple implementation, + only parses the 'fsl,pins' property and configure related + registers. diff --git a/drivers/pinctrl/nxp/Makefile b/drivers/pinctrl/nxp/Makefile index e0f73251026..c7639483769 100644 --- a/drivers/pinctrl/nxp/Makefile +++ b/drivers/pinctrl/nxp/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o obj-$(CONFIG_PINCTRL_IMX5) += pinctrl-imx5.o obj-$(CONFIG_PINCTRL_IMX6) += pinctrl-imx6.o obj-$(CONFIG_PINCTRL_IMX7) += pinctrl-imx7.o +obj-$(CONFIG_PINCTRL_IMX7ULP) += pinctrl-imx7ulp.o diff --git a/drivers/pinctrl/nxp/pinctrl-imx.c b/drivers/pinctrl/nxp/pinctrl-imx.c index e130faf8764..f0321c40576 100644 --- a/drivers/pinctrl/nxp/pinctrl-imx.c +++ b/drivers/pinctrl/nxp/pinctrl-imx.c @@ -24,6 +24,7 @@ static int imx_pinctrl_set_state(struct udevice *dev, struct udevice *config) u32 *pin_data; int npins, size, pin_size; int mux_reg, conf_reg, input_reg, input_val, mux_mode, config_val; + u32 mux_shift = info->mux_mask ? ffs(info->mux_mask) - 1 : 0; int i, j = 0; dev_dbg(dev, "%s: %s\n", __func__, config->name); @@ -97,8 +98,8 @@ static int imx_pinctrl_set_state(struct udevice *dev, struct udevice *config) /* Set Mux */ if (info->flags & SHARE_MUX_CONF_REG) { - clrsetbits_le32(info->base + mux_reg, 0x7 << 20, - mux_mode << 20); + clrsetbits_le32(info->base + mux_reg, info->mux_mask, + mux_mode << mux_shift); } else { writel(mux_mode, info->base + mux_reg); } @@ -154,8 +155,8 @@ static int imx_pinctrl_set_state(struct udevice *dev, struct udevice *config) /* Set config */ if (!(config_val & IMX_NO_PAD_CTL)) { if (info->flags & SHARE_MUX_CONF_REG) { - clrsetbits_le32(info->base + conf_reg, 0xffff, - config_val); + clrsetbits_le32(info->base + conf_reg, + info->mux_mask, config_val); } else { writel(config_val, info->base + conf_reg); } @@ -200,6 +201,7 @@ int imx_pinctrl_probe(struct udevice *dev, return -ENOMEM; priv->info = info; + info->mux_mask = fdtdec_get_int(gd->fdt_blob, node, "fsl,mux_mask", 0); /* * Refer to linux documentation for details: * Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt diff --git a/drivers/pinctrl/nxp/pinctrl-imx.h b/drivers/pinctrl/nxp/pinctrl-imx.h index 037c4915808..a26ba854c13 100644 --- a/drivers/pinctrl/nxp/pinctrl-imx.h +++ b/drivers/pinctrl/nxp/pinctrl-imx.h @@ -11,11 +11,13 @@ * @base: the address to the controller in virtual memory * @input_sel_base: the address of the select input in virtual memory. * @flags: flags specific for each soc + * @mux_mask: Used when SHARE_MUX_CONF_REG flag is added */ struct imx_pinctrl_soc_info { void __iomem *base; void __iomem *input_sel_base; unsigned int flags; + unsigned int mux_mask; }; /** @@ -41,6 +43,7 @@ extern const struct pinctrl_ops imx_pinctrl_ops; #define SHARE_MUX_CONF_REG 0x1 #define ZERO_OFFSET_VALID 0x2 +#define CONFIG_IBE_OBE 0x4 #define IOMUXC_CONFIG_SION (0x1 << 4) diff --git a/drivers/pinctrl/nxp/pinctrl-imx7ulp.c b/drivers/pinctrl/nxp/pinctrl-imx7ulp.c new file mode 100644 index 00000000000..5f011757d8c --- /dev/null +++ b/drivers/pinctrl/nxp/pinctrl-imx7ulp.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * Peng Fan + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#include "pinctrl-imx.h" + +static struct imx_pinctrl_soc_info imx7ulp_pinctrl_soc_info = { + .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CONFIG_IBE_OBE, +}; + +static int imx7ulp_pinctrl_probe(struct udevice *dev) +{ + struct imx_pinctrl_soc_info *info = + (struct imx_pinctrl_soc_info *)dev_get_driver_data(dev); + + return imx_pinctrl_probe(dev, info); +} + +static const struct udevice_id imx7ulp_pinctrl_match[] = { + { .compatible = "fsl,imx7ulp-iomuxc-0", .data = (ulong)&imx7ulp_pinctrl_soc_info }, + { .compatible = "fsl,imx7ulp-iomuxc-1", .data = (ulong)&imx7ulp_pinctrl_soc_info }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(imx7ulp_pinctrl) = { + .name = "imx7ulp-pinctrl", + .id = UCLASS_PINCTRL, + .of_match = of_match_ptr(imx7ulp_pinctrl_match), + .probe = imx7ulp_pinctrl_probe, + .remove = imx_pinctrl_remove, + .priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv), + .ops = &imx_pinctrl_ops, + .flags = DM_FLAG_PRE_RELOC, +}; -- cgit v1.3.1 From 7ee3f149fe776d3e46dbb517bf04ee29ec075709 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 24 Feb 2017 09:54:18 +0800 Subject: i2c: lpi2c: add lpi2c driver for i.MX7ULP Add lpi2c driver for i.MX7ULP. Need to enable the two options to use this driver: CONFIG_DM_I2C=y CONFIG_SYS_I2C_IMX_LPI2C=y Signed-off-by: Peng Fan Acked-by: Heiko Schocher Cc: Stefano Babic --- arch/arm/include/asm/arch-mx7ulp/imx_lpi2c.h | 520 +++++++++++++++++++++++++++ drivers/i2c/Kconfig | 6 + drivers/i2c/Makefile | 1 + drivers/i2c/imx_lpi2c.c | 462 ++++++++++++++++++++++++ 4 files changed, 989 insertions(+) create mode 100644 arch/arm/include/asm/arch-mx7ulp/imx_lpi2c.h create mode 100644 drivers/i2c/imx_lpi2c.c (limited to 'drivers') diff --git a/arch/arm/include/asm/arch-mx7ulp/imx_lpi2c.h b/arch/arm/include/asm/arch-mx7ulp/imx_lpi2c.h new file mode 100644 index 00000000000..f1b31137907 --- /dev/null +++ b/arch/arm/include/asm/arch-mx7ulp/imx_lpi2c.h @@ -0,0 +1,520 @@ +/* + * Copyright 2016 Freescale Semiconductors, Inc. + * + * I2CLP driver for i.MX + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ +#ifndef __IMX_LPI2C_H__ +#define __IMX_LPI2C_H__ + +struct imx_lpi2c_bus { + int index; + ulong base; + ulong driver_data; + int speed; + struct i2c_pads_info *pads_info; + struct udevice *bus; +}; + +struct imx_lpi2c_reg { + u32 verid; + u32 param; + u8 reserved_0[8]; + u32 mcr; + u32 msr; + u32 mier; + u32 mder; + u32 mcfgr0; + u32 mcfgr1; + u32 mcfgr2; + u32 mcfgr3; + u8 reserved_1[16]; + u32 mdmr; + u8 reserved_2[4]; + u32 mccr0; + u8 reserved_3[4]; + u32 mccr1; + u8 reserved_4[4]; + u32 mfcr; + u32 mfsr; + u32 mtdr; + u8 reserved_5[12]; + u32 mrdr; + u8 reserved_6[156]; + u32 scr; + u32 ssr; + u32 sier; + u32 sder; + u8 reserved_7[4]; + u32 scfgr1; + u32 scfgr2; + u8 reserved_8[20]; + u32 samr; + u8 reserved_9[12]; + u32 sasr; + u32 star; + u8 reserved_10[8]; + u32 stdr; + u8 reserved_11[12]; + u32 srdr; +}; + +typedef enum lpi2c_status { + LPI2C_SUCESS = 0, + LPI2C_END_PACKET_ERR, + LPI2C_STOP_ERR, + LPI2C_NAK_ERR, + LPI2C_ARB_LOST_ERR, + LPI2C_FIFO_ERR, + LPI2C_PIN_LOW_TIMEOUT_ERR, + LPI2C_DATA_MATCH_ERR, + LPI2C_BUSY, + LPI2C_IDLE, + LPI2C_BIT_ERR, + LPI2C_NO_TRANS_PROG, + LPI2C_DMA_REQ_FAIL, +} lpi2c_status_t; + +/* ---------------------------------------------------------------------------- + -- LPI2C Register Masks + ---------------------------------------------------------------------------- */ + +/*! + * @addtogroup LPI2C_Register_Masks LPI2C Register Masks + * @{ + */ + +/*! @name VERID - Version ID Register */ +#define LPI2C_VERID_FEATURE_MASK (0xFFFFU) +#define LPI2C_VERID_FEATURE_SHIFT (0U) +#define LPI2C_VERID_FEATURE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_VERID_FEATURE_SHIFT)) & LPI2C_VERID_FEATURE_MASK) +#define LPI2C_VERID_MINOR_MASK (0xFF0000U) +#define LPI2C_VERID_MINOR_SHIFT (16U) +#define LPI2C_VERID_MINOR(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_VERID_MINOR_SHIFT)) & LPI2C_VERID_MINOR_MASK) +#define LPI2C_VERID_MAJOR_MASK (0xFF000000U) +#define LPI2C_VERID_MAJOR_SHIFT (24U) +#define LPI2C_VERID_MAJOR(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_VERID_MAJOR_SHIFT)) & LPI2C_VERID_MAJOR_MASK) + +/*! @name PARAM - Parameter Register */ +#define LPI2C_PARAM_MTXFIFO_MASK (0xFU) +#define LPI2C_PARAM_MTXFIFO_SHIFT (0U) +#define LPI2C_PARAM_MTXFIFO(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_PARAM_MTXFIFO_SHIFT)) & LPI2C_PARAM_MTXFIFO_MASK) +#define LPI2C_PARAM_MRXFIFO_MASK (0xF00U) +#define LPI2C_PARAM_MRXFIFO_SHIFT (8U) +#define LPI2C_PARAM_MRXFIFO(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_PARAM_MRXFIFO_SHIFT)) & LPI2C_PARAM_MRXFIFO_MASK) + +/*! @name MCR - Master Control Register */ +#define LPI2C_MCR_MEN_MASK (0x1U) +#define LPI2C_MCR_MEN_SHIFT (0U) +#define LPI2C_MCR_MEN(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCR_MEN_SHIFT)) & LPI2C_MCR_MEN_MASK) +#define LPI2C_MCR_RST_MASK (0x2U) +#define LPI2C_MCR_RST_SHIFT (1U) +#define LPI2C_MCR_RST(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCR_RST_SHIFT)) & LPI2C_MCR_RST_MASK) +#define LPI2C_MCR_DOZEN_MASK (0x4U) +#define LPI2C_MCR_DOZEN_SHIFT (2U) +#define LPI2C_MCR_DOZEN(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCR_DOZEN_SHIFT)) & LPI2C_MCR_DOZEN_MASK) +#define LPI2C_MCR_DBGEN_MASK (0x8U) +#define LPI2C_MCR_DBGEN_SHIFT (3U) +#define LPI2C_MCR_DBGEN(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCR_DBGEN_SHIFT)) & LPI2C_MCR_DBGEN_MASK) +#define LPI2C_MCR_RTF_MASK (0x100U) +#define LPI2C_MCR_RTF_SHIFT (8U) +#define LPI2C_MCR_RTF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCR_RTF_SHIFT)) & LPI2C_MCR_RTF_MASK) +#define LPI2C_MCR_RRF_MASK (0x200U) +#define LPI2C_MCR_RRF_SHIFT (9U) +#define LPI2C_MCR_RRF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCR_RRF_SHIFT)) & LPI2C_MCR_RRF_MASK) + +/*! @name MSR - Master Status Register */ +#define LPI2C_MSR_TDF_MASK (0x1U) +#define LPI2C_MSR_TDF_SHIFT (0U) +#define LPI2C_MSR_TDF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_TDF_SHIFT)) & LPI2C_MSR_TDF_MASK) +#define LPI2C_MSR_RDF_MASK (0x2U) +#define LPI2C_MSR_RDF_SHIFT (1U) +#define LPI2C_MSR_RDF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_RDF_SHIFT)) & LPI2C_MSR_RDF_MASK) +#define LPI2C_MSR_EPF_MASK (0x100U) +#define LPI2C_MSR_EPF_SHIFT (8U) +#define LPI2C_MSR_EPF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_EPF_SHIFT)) & LPI2C_MSR_EPF_MASK) +#define LPI2C_MSR_SDF_MASK (0x200U) +#define LPI2C_MSR_SDF_SHIFT (9U) +#define LPI2C_MSR_SDF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_SDF_SHIFT)) & LPI2C_MSR_SDF_MASK) +#define LPI2C_MSR_NDF_MASK (0x400U) +#define LPI2C_MSR_NDF_SHIFT (10U) +#define LPI2C_MSR_NDF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_NDF_SHIFT)) & LPI2C_MSR_NDF_MASK) +#define LPI2C_MSR_ALF_MASK (0x800U) +#define LPI2C_MSR_ALF_SHIFT (11U) +#define LPI2C_MSR_ALF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_ALF_SHIFT)) & LPI2C_MSR_ALF_MASK) +#define LPI2C_MSR_FEF_MASK (0x1000U) +#define LPI2C_MSR_FEF_SHIFT (12U) +#define LPI2C_MSR_FEF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_FEF_SHIFT)) & LPI2C_MSR_FEF_MASK) +#define LPI2C_MSR_PLTF_MASK (0x2000U) +#define LPI2C_MSR_PLTF_SHIFT (13U) +#define LPI2C_MSR_PLTF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_PLTF_SHIFT)) & LPI2C_MSR_PLTF_MASK) +#define LPI2C_MSR_DMF_MASK (0x4000U) +#define LPI2C_MSR_DMF_SHIFT (14U) +#define LPI2C_MSR_DMF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_DMF_SHIFT)) & LPI2C_MSR_DMF_MASK) +#define LPI2C_MSR_MBF_MASK (0x1000000U) +#define LPI2C_MSR_MBF_SHIFT (24U) +#define LPI2C_MSR_MBF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_MBF_SHIFT)) & LPI2C_MSR_MBF_MASK) +#define LPI2C_MSR_BBF_MASK (0x2000000U) +#define LPI2C_MSR_BBF_SHIFT (25U) +#define LPI2C_MSR_BBF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MSR_BBF_SHIFT)) & LPI2C_MSR_BBF_MASK) + +/*! @name MIER - Master Interrupt Enable Register */ +#define LPI2C_MIER_TDIE_MASK (0x1U) +#define LPI2C_MIER_TDIE_SHIFT (0U) +#define LPI2C_MIER_TDIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MIER_TDIE_SHIFT)) & LPI2C_MIER_TDIE_MASK) +#define LPI2C_MIER_RDIE_MASK (0x2U) +#define LPI2C_MIER_RDIE_SHIFT (1U) +#define LPI2C_MIER_RDIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MIER_RDIE_SHIFT)) & LPI2C_MIER_RDIE_MASK) +#define LPI2C_MIER_EPIE_MASK (0x100U) +#define LPI2C_MIER_EPIE_SHIFT (8U) +#define LPI2C_MIER_EPIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MIER_EPIE_SHIFT)) & LPI2C_MIER_EPIE_MASK) +#define LPI2C_MIER_SDIE_MASK (0x200U) +#define LPI2C_MIER_SDIE_SHIFT (9U) +#define LPI2C_MIER_SDIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MIER_SDIE_SHIFT)) & LPI2C_MIER_SDIE_MASK) +#define LPI2C_MIER_NDIE_MASK (0x400U) +#define LPI2C_MIER_NDIE_SHIFT (10U) +#define LPI2C_MIER_NDIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MIER_NDIE_SHIFT)) & LPI2C_MIER_NDIE_MASK) +#define LPI2C_MIER_ALIE_MASK (0x800U) +#define LPI2C_MIER_ALIE_SHIFT (11U) +#define LPI2C_MIER_ALIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MIER_ALIE_SHIFT)) & LPI2C_MIER_ALIE_MASK) +#define LPI2C_MIER_FEIE_MASK (0x1000U) +#define LPI2C_MIER_FEIE_SHIFT (12U) +#define LPI2C_MIER_FEIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MIER_FEIE_SHIFT)) & LPI2C_MIER_FEIE_MASK) +#define LPI2C_MIER_PLTIE_MASK (0x2000U) +#define LPI2C_MIER_PLTIE_SHIFT (13U) +#define LPI2C_MIER_PLTIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MIER_PLTIE_SHIFT)) & LPI2C_MIER_PLTIE_MASK) +#define LPI2C_MIER_DMIE_MASK (0x4000U) +#define LPI2C_MIER_DMIE_SHIFT (14U) +#define LPI2C_MIER_DMIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MIER_DMIE_SHIFT)) & LPI2C_MIER_DMIE_MASK) + +/*! @name MDER - Master DMA Enable Register */ +#define LPI2C_MDER_TDDE_MASK (0x1U) +#define LPI2C_MDER_TDDE_SHIFT (0U) +#define LPI2C_MDER_TDDE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MDER_TDDE_SHIFT)) & LPI2C_MDER_TDDE_MASK) +#define LPI2C_MDER_RDDE_MASK (0x2U) +#define LPI2C_MDER_RDDE_SHIFT (1U) +#define LPI2C_MDER_RDDE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MDER_RDDE_SHIFT)) & LPI2C_MDER_RDDE_MASK) + +/*! @name MCFGR0 - Master Configuration Register 0 */ +#define LPI2C_MCFGR0_HREN_MASK (0x1U) +#define LPI2C_MCFGR0_HREN_SHIFT (0U) +#define LPI2C_MCFGR0_HREN(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR0_HREN_SHIFT)) & LPI2C_MCFGR0_HREN_MASK) +#define LPI2C_MCFGR0_HRPOL_MASK (0x2U) +#define LPI2C_MCFGR0_HRPOL_SHIFT (1U) +#define LPI2C_MCFGR0_HRPOL(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR0_HRPOL_SHIFT)) & LPI2C_MCFGR0_HRPOL_MASK) +#define LPI2C_MCFGR0_HRSEL_MASK (0x4U) +#define LPI2C_MCFGR0_HRSEL_SHIFT (2U) +#define LPI2C_MCFGR0_HRSEL(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR0_HRSEL_SHIFT)) & LPI2C_MCFGR0_HRSEL_MASK) +#define LPI2C_MCFGR0_CIRFIFO_MASK (0x100U) +#define LPI2C_MCFGR0_CIRFIFO_SHIFT (8U) +#define LPI2C_MCFGR0_CIRFIFO(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR0_CIRFIFO_SHIFT)) & LPI2C_MCFGR0_CIRFIFO_MASK) +#define LPI2C_MCFGR0_RDMO_MASK (0x200U) +#define LPI2C_MCFGR0_RDMO_SHIFT (9U) +#define LPI2C_MCFGR0_RDMO(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR0_RDMO_SHIFT)) & LPI2C_MCFGR0_RDMO_MASK) + +/*! @name MCFGR1 - Master Configuration Register 1 */ +#define LPI2C_MCFGR1_PRESCALE_MASK (0x7U) +#define LPI2C_MCFGR1_PRESCALE_SHIFT (0U) +#define LPI2C_MCFGR1_PRESCALE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR1_PRESCALE_SHIFT)) & LPI2C_MCFGR1_PRESCALE_MASK) +#define LPI2C_MCFGR1_AUTOSTOP_MASK (0x100U) +#define LPI2C_MCFGR1_AUTOSTOP_SHIFT (8U) +#define LPI2C_MCFGR1_AUTOSTOP(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR1_AUTOSTOP_SHIFT)) & LPI2C_MCFGR1_AUTOSTOP_MASK) +#define LPI2C_MCFGR1_IGNACK_MASK (0x200U) +#define LPI2C_MCFGR1_IGNACK_SHIFT (9U) +#define LPI2C_MCFGR1_IGNACK(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR1_IGNACK_SHIFT)) & LPI2C_MCFGR1_IGNACK_MASK) +#define LPI2C_MCFGR1_TIMECFG_MASK (0x400U) +#define LPI2C_MCFGR1_TIMECFG_SHIFT (10U) +#define LPI2C_MCFGR1_TIMECFG(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR1_TIMECFG_SHIFT)) & LPI2C_MCFGR1_TIMECFG_MASK) +#define LPI2C_MCFGR1_MATCFG_MASK (0x70000U) +#define LPI2C_MCFGR1_MATCFG_SHIFT (16U) +#define LPI2C_MCFGR1_MATCFG(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR1_MATCFG_SHIFT)) & LPI2C_MCFGR1_MATCFG_MASK) +#define LPI2C_MCFGR1_PINCFG_MASK (0x7000000U) +#define LPI2C_MCFGR1_PINCFG_SHIFT (24U) +#define LPI2C_MCFGR1_PINCFG(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR1_PINCFG_SHIFT)) & LPI2C_MCFGR1_PINCFG_MASK) + +/*! @name MCFGR2 - Master Configuration Register 2 */ +#define LPI2C_MCFGR2_BUSIDLE_MASK (0xFFFU) +#define LPI2C_MCFGR2_BUSIDLE_SHIFT (0U) +#define LPI2C_MCFGR2_BUSIDLE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR2_BUSIDLE_SHIFT)) & LPI2C_MCFGR2_BUSIDLE_MASK) +#define LPI2C_MCFGR2_FILTSCL_MASK (0xF0000U) +#define LPI2C_MCFGR2_FILTSCL_SHIFT (16U) +#define LPI2C_MCFGR2_FILTSCL(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR2_FILTSCL_SHIFT)) & LPI2C_MCFGR2_FILTSCL_MASK) +#define LPI2C_MCFGR2_FILTSDA_MASK (0xF000000U) +#define LPI2C_MCFGR2_FILTSDA_SHIFT (24U) +#define LPI2C_MCFGR2_FILTSDA(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR2_FILTSDA_SHIFT)) & LPI2C_MCFGR2_FILTSDA_MASK) + +/*! @name MCFGR3 - Master Configuration Register 3 */ +#define LPI2C_MCFGR3_PINLOW_MASK (0xFFF00U) +#define LPI2C_MCFGR3_PINLOW_SHIFT (8U) +#define LPI2C_MCFGR3_PINLOW(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCFGR3_PINLOW_SHIFT)) & LPI2C_MCFGR3_PINLOW_MASK) + +/*! @name MDMR - Master Data Match Register */ +#define LPI2C_MDMR_MATCH0_MASK (0xFFU) +#define LPI2C_MDMR_MATCH0_SHIFT (0U) +#define LPI2C_MDMR_MATCH0(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MDMR_MATCH0_SHIFT)) & LPI2C_MDMR_MATCH0_MASK) +#define LPI2C_MDMR_MATCH1_MASK (0xFF0000U) +#define LPI2C_MDMR_MATCH1_SHIFT (16U) +#define LPI2C_MDMR_MATCH1(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MDMR_MATCH1_SHIFT)) & LPI2C_MDMR_MATCH1_MASK) + +/*! @name MCCR0 - Master Clock Configuration Register 0 */ +#define LPI2C_MCCR0_CLKLO_MASK (0x3FU) +#define LPI2C_MCCR0_CLKLO_SHIFT (0U) +#define LPI2C_MCCR0_CLKLO(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCCR0_CLKLO_SHIFT)) & LPI2C_MCCR0_CLKLO_MASK) +#define LPI2C_MCCR0_CLKHI_MASK (0x3F00U) +#define LPI2C_MCCR0_CLKHI_SHIFT (8U) +#define LPI2C_MCCR0_CLKHI(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCCR0_CLKHI_SHIFT)) & LPI2C_MCCR0_CLKHI_MASK) +#define LPI2C_MCCR0_SETHOLD_MASK (0x3F0000U) +#define LPI2C_MCCR0_SETHOLD_SHIFT (16U) +#define LPI2C_MCCR0_SETHOLD(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCCR0_SETHOLD_SHIFT)) & LPI2C_MCCR0_SETHOLD_MASK) +#define LPI2C_MCCR0_DATAVD_MASK (0x3F000000U) +#define LPI2C_MCCR0_DATAVD_SHIFT (24U) +#define LPI2C_MCCR0_DATAVD(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCCR0_DATAVD_SHIFT)) & LPI2C_MCCR0_DATAVD_MASK) + +/*! @name MCCR1 - Master Clock Configuration Register 1 */ +#define LPI2C_MCCR1_CLKLO_MASK (0x3FU) +#define LPI2C_MCCR1_CLKLO_SHIFT (0U) +#define LPI2C_MCCR1_CLKLO(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCCR1_CLKLO_SHIFT)) & LPI2C_MCCR1_CLKLO_MASK) +#define LPI2C_MCCR1_CLKHI_MASK (0x3F00U) +#define LPI2C_MCCR1_CLKHI_SHIFT (8U) +#define LPI2C_MCCR1_CLKHI(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCCR1_CLKHI_SHIFT)) & LPI2C_MCCR1_CLKHI_MASK) +#define LPI2C_MCCR1_SETHOLD_MASK (0x3F0000U) +#define LPI2C_MCCR1_SETHOLD_SHIFT (16U) +#define LPI2C_MCCR1_SETHOLD(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCCR1_SETHOLD_SHIFT)) & LPI2C_MCCR1_SETHOLD_MASK) +#define LPI2C_MCCR1_DATAVD_MASK (0x3F000000U) +#define LPI2C_MCCR1_DATAVD_SHIFT (24U) +#define LPI2C_MCCR1_DATAVD(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MCCR1_DATAVD_SHIFT)) & LPI2C_MCCR1_DATAVD_MASK) + +/*! @name MFCR - Master FIFO Control Register */ +#define LPI2C_MFCR_TXWATER_MASK (0xFFU) +#define LPI2C_MFCR_TXWATER_SHIFT (0U) +#define LPI2C_MFCR_TXWATER(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MFCR_TXWATER_SHIFT)) & LPI2C_MFCR_TXWATER_MASK) +#define LPI2C_MFCR_RXWATER_MASK (0xFF0000U) +#define LPI2C_MFCR_RXWATER_SHIFT (16U) +#define LPI2C_MFCR_RXWATER(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MFCR_RXWATER_SHIFT)) & LPI2C_MFCR_RXWATER_MASK) + +/*! @name MFSR - Master FIFO Status Register */ +#define LPI2C_MFSR_TXCOUNT_MASK (0xFFU) +#define LPI2C_MFSR_TXCOUNT_SHIFT (0U) +#define LPI2C_MFSR_TXCOUNT(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MFSR_TXCOUNT_SHIFT)) & LPI2C_MFSR_TXCOUNT_MASK) +#define LPI2C_MFSR_RXCOUNT_MASK (0xFF0000U) +#define LPI2C_MFSR_RXCOUNT_SHIFT (16U) +#define LPI2C_MFSR_RXCOUNT(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MFSR_RXCOUNT_SHIFT)) & LPI2C_MFSR_RXCOUNT_MASK) + +/*! @name MTDR - Master Transmit Data Register */ +#define LPI2C_MTDR_DATA_MASK (0xFFU) +#define LPI2C_MTDR_DATA_SHIFT (0U) +#define LPI2C_MTDR_DATA(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MTDR_DATA_SHIFT)) & LPI2C_MTDR_DATA_MASK) +#define LPI2C_MTDR_CMD_MASK (0x700U) +#define LPI2C_MTDR_CMD_SHIFT (8U) +#define LPI2C_MTDR_CMD(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MTDR_CMD_SHIFT)) & LPI2C_MTDR_CMD_MASK) + +/*! @name MRDR - Master Receive Data Register */ +#define LPI2C_MRDR_DATA_MASK (0xFFU) +#define LPI2C_MRDR_DATA_SHIFT (0U) +#define LPI2C_MRDR_DATA(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MRDR_DATA_SHIFT)) & LPI2C_MRDR_DATA_MASK) +#define LPI2C_MRDR_RXEMPTY_MASK (0x4000U) +#define LPI2C_MRDR_RXEMPTY_SHIFT (14U) +#define LPI2C_MRDR_RXEMPTY(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_MRDR_RXEMPTY_SHIFT)) & LPI2C_MRDR_RXEMPTY_MASK) + +/*! @name SCR - Slave Control Register */ +#define LPI2C_SCR_SEN_MASK (0x1U) +#define LPI2C_SCR_SEN_SHIFT (0U) +#define LPI2C_SCR_SEN(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCR_SEN_SHIFT)) & LPI2C_SCR_SEN_MASK) +#define LPI2C_SCR_RST_MASK (0x2U) +#define LPI2C_SCR_RST_SHIFT (1U) +#define LPI2C_SCR_RST(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCR_RST_SHIFT)) & LPI2C_SCR_RST_MASK) +#define LPI2C_SCR_FILTEN_MASK (0x10U) +#define LPI2C_SCR_FILTEN_SHIFT (4U) +#define LPI2C_SCR_FILTEN(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCR_FILTEN_SHIFT)) & LPI2C_SCR_FILTEN_MASK) +#define LPI2C_SCR_FILTDZ_MASK (0x20U) +#define LPI2C_SCR_FILTDZ_SHIFT (5U) +#define LPI2C_SCR_FILTDZ(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCR_FILTDZ_SHIFT)) & LPI2C_SCR_FILTDZ_MASK) +#define LPI2C_SCR_RTF_MASK (0x100U) +#define LPI2C_SCR_RTF_SHIFT (8U) +#define LPI2C_SCR_RTF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCR_RTF_SHIFT)) & LPI2C_SCR_RTF_MASK) +#define LPI2C_SCR_RRF_MASK (0x200U) +#define LPI2C_SCR_RRF_SHIFT (9U) +#define LPI2C_SCR_RRF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCR_RRF_SHIFT)) & LPI2C_SCR_RRF_MASK) + +/*! @name SSR - Slave Status Register */ +#define LPI2C_SSR_TDF_MASK (0x1U) +#define LPI2C_SSR_TDF_SHIFT (0U) +#define LPI2C_SSR_TDF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_TDF_SHIFT)) & LPI2C_SSR_TDF_MASK) +#define LPI2C_SSR_RDF_MASK (0x2U) +#define LPI2C_SSR_RDF_SHIFT (1U) +#define LPI2C_SSR_RDF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_RDF_SHIFT)) & LPI2C_SSR_RDF_MASK) +#define LPI2C_SSR_AVF_MASK (0x4U) +#define LPI2C_SSR_AVF_SHIFT (2U) +#define LPI2C_SSR_AVF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_AVF_SHIFT)) & LPI2C_SSR_AVF_MASK) +#define LPI2C_SSR_TAF_MASK (0x8U) +#define LPI2C_SSR_TAF_SHIFT (3U) +#define LPI2C_SSR_TAF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_TAF_SHIFT)) & LPI2C_SSR_TAF_MASK) +#define LPI2C_SSR_RSF_MASK (0x100U) +#define LPI2C_SSR_RSF_SHIFT (8U) +#define LPI2C_SSR_RSF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_RSF_SHIFT)) & LPI2C_SSR_RSF_MASK) +#define LPI2C_SSR_SDF_MASK (0x200U) +#define LPI2C_SSR_SDF_SHIFT (9U) +#define LPI2C_SSR_SDF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_SDF_SHIFT)) & LPI2C_SSR_SDF_MASK) +#define LPI2C_SSR_BEF_MASK (0x400U) +#define LPI2C_SSR_BEF_SHIFT (10U) +#define LPI2C_SSR_BEF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_BEF_SHIFT)) & LPI2C_SSR_BEF_MASK) +#define LPI2C_SSR_FEF_MASK (0x800U) +#define LPI2C_SSR_FEF_SHIFT (11U) +#define LPI2C_SSR_FEF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_FEF_SHIFT)) & LPI2C_SSR_FEF_MASK) +#define LPI2C_SSR_AM0F_MASK (0x1000U) +#define LPI2C_SSR_AM0F_SHIFT (12U) +#define LPI2C_SSR_AM0F(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_AM0F_SHIFT)) & LPI2C_SSR_AM0F_MASK) +#define LPI2C_SSR_AM1F_MASK (0x2000U) +#define LPI2C_SSR_AM1F_SHIFT (13U) +#define LPI2C_SSR_AM1F(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_AM1F_SHIFT)) & LPI2C_SSR_AM1F_MASK) +#define LPI2C_SSR_GCF_MASK (0x4000U) +#define LPI2C_SSR_GCF_SHIFT (14U) +#define LPI2C_SSR_GCF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_GCF_SHIFT)) & LPI2C_SSR_GCF_MASK) +#define LPI2C_SSR_SARF_MASK (0x8000U) +#define LPI2C_SSR_SARF_SHIFT (15U) +#define LPI2C_SSR_SARF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_SARF_SHIFT)) & LPI2C_SSR_SARF_MASK) +#define LPI2C_SSR_SBF_MASK (0x1000000U) +#define LPI2C_SSR_SBF_SHIFT (24U) +#define LPI2C_SSR_SBF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_SBF_SHIFT)) & LPI2C_SSR_SBF_MASK) +#define LPI2C_SSR_BBF_MASK (0x2000000U) +#define LPI2C_SSR_BBF_SHIFT (25U) +#define LPI2C_SSR_BBF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SSR_BBF_SHIFT)) & LPI2C_SSR_BBF_MASK) + +/*! @name SIER - Slave Interrupt Enable Register */ +#define LPI2C_SIER_TDIE_MASK (0x1U) +#define LPI2C_SIER_TDIE_SHIFT (0U) +#define LPI2C_SIER_TDIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_TDIE_SHIFT)) & LPI2C_SIER_TDIE_MASK) +#define LPI2C_SIER_RDIE_MASK (0x2U) +#define LPI2C_SIER_RDIE_SHIFT (1U) +#define LPI2C_SIER_RDIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_RDIE_SHIFT)) & LPI2C_SIER_RDIE_MASK) +#define LPI2C_SIER_AVIE_MASK (0x4U) +#define LPI2C_SIER_AVIE_SHIFT (2U) +#define LPI2C_SIER_AVIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_AVIE_SHIFT)) & LPI2C_SIER_AVIE_MASK) +#define LPI2C_SIER_TAIE_MASK (0x8U) +#define LPI2C_SIER_TAIE_SHIFT (3U) +#define LPI2C_SIER_TAIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_TAIE_SHIFT)) & LPI2C_SIER_TAIE_MASK) +#define LPI2C_SIER_RSIE_MASK (0x100U) +#define LPI2C_SIER_RSIE_SHIFT (8U) +#define LPI2C_SIER_RSIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_RSIE_SHIFT)) & LPI2C_SIER_RSIE_MASK) +#define LPI2C_SIER_SDIE_MASK (0x200U) +#define LPI2C_SIER_SDIE_SHIFT (9U) +#define LPI2C_SIER_SDIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_SDIE_SHIFT)) & LPI2C_SIER_SDIE_MASK) +#define LPI2C_SIER_BEIE_MASK (0x400U) +#define LPI2C_SIER_BEIE_SHIFT (10U) +#define LPI2C_SIER_BEIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_BEIE_SHIFT)) & LPI2C_SIER_BEIE_MASK) +#define LPI2C_SIER_FEIE_MASK (0x800U) +#define LPI2C_SIER_FEIE_SHIFT (11U) +#define LPI2C_SIER_FEIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_FEIE_SHIFT)) & LPI2C_SIER_FEIE_MASK) +#define LPI2C_SIER_AM0IE_MASK (0x1000U) +#define LPI2C_SIER_AM0IE_SHIFT (12U) +#define LPI2C_SIER_AM0IE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_AM0IE_SHIFT)) & LPI2C_SIER_AM0IE_MASK) +#define LPI2C_SIER_AM1F_MASK (0x2000U) +#define LPI2C_SIER_AM1F_SHIFT (13U) +#define LPI2C_SIER_AM1F(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_AM1F_SHIFT)) & LPI2C_SIER_AM1F_MASK) +#define LPI2C_SIER_GCIE_MASK (0x4000U) +#define LPI2C_SIER_GCIE_SHIFT (14U) +#define LPI2C_SIER_GCIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_GCIE_SHIFT)) & LPI2C_SIER_GCIE_MASK) +#define LPI2C_SIER_SARIE_MASK (0x8000U) +#define LPI2C_SIER_SARIE_SHIFT (15U) +#define LPI2C_SIER_SARIE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SIER_SARIE_SHIFT)) & LPI2C_SIER_SARIE_MASK) + +/*! @name SDER - Slave DMA Enable Register */ +#define LPI2C_SDER_TDDE_MASK (0x1U) +#define LPI2C_SDER_TDDE_SHIFT (0U) +#define LPI2C_SDER_TDDE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SDER_TDDE_SHIFT)) & LPI2C_SDER_TDDE_MASK) +#define LPI2C_SDER_RDDE_MASK (0x2U) +#define LPI2C_SDER_RDDE_SHIFT (1U) +#define LPI2C_SDER_RDDE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SDER_RDDE_SHIFT)) & LPI2C_SDER_RDDE_MASK) +#define LPI2C_SDER_AVDE_MASK (0x4U) +#define LPI2C_SDER_AVDE_SHIFT (2U) +#define LPI2C_SDER_AVDE(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SDER_AVDE_SHIFT)) & LPI2C_SDER_AVDE_MASK) + +/*! @name SCFGR1 - Slave Configuration Register 1 */ +#define LPI2C_SCFGR1_ADRSTALL_MASK (0x1U) +#define LPI2C_SCFGR1_ADRSTALL_SHIFT (0U) +#define LPI2C_SCFGR1_ADRSTALL(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_ADRSTALL_SHIFT)) & LPI2C_SCFGR1_ADRSTALL_MASK) +#define LPI2C_SCFGR1_RXSTALL_MASK (0x2U) +#define LPI2C_SCFGR1_RXSTALL_SHIFT (1U) +#define LPI2C_SCFGR1_RXSTALL(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_RXSTALL_SHIFT)) & LPI2C_SCFGR1_RXSTALL_MASK) +#define LPI2C_SCFGR1_TXDSTALL_MASK (0x4U) +#define LPI2C_SCFGR1_TXDSTALL_SHIFT (2U) +#define LPI2C_SCFGR1_TXDSTALL(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_TXDSTALL_SHIFT)) & LPI2C_SCFGR1_TXDSTALL_MASK) +#define LPI2C_SCFGR1_ACKSTALL_MASK (0x8U) +#define LPI2C_SCFGR1_ACKSTALL_SHIFT (3U) +#define LPI2C_SCFGR1_ACKSTALL(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_ACKSTALL_SHIFT)) & LPI2C_SCFGR1_ACKSTALL_MASK) +#define LPI2C_SCFGR1_GCEN_MASK (0x100U) +#define LPI2C_SCFGR1_GCEN_SHIFT (8U) +#define LPI2C_SCFGR1_GCEN(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_GCEN_SHIFT)) & LPI2C_SCFGR1_GCEN_MASK) +#define LPI2C_SCFGR1_SAEN_MASK (0x200U) +#define LPI2C_SCFGR1_SAEN_SHIFT (9U) +#define LPI2C_SCFGR1_SAEN(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_SAEN_SHIFT)) & LPI2C_SCFGR1_SAEN_MASK) +#define LPI2C_SCFGR1_TXCFG_MASK (0x400U) +#define LPI2C_SCFGR1_TXCFG_SHIFT (10U) +#define LPI2C_SCFGR1_TXCFG(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_TXCFG_SHIFT)) & LPI2C_SCFGR1_TXCFG_MASK) +#define LPI2C_SCFGR1_RXCFG_MASK (0x800U) +#define LPI2C_SCFGR1_RXCFG_SHIFT (11U) +#define LPI2C_SCFGR1_RXCFG(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_RXCFG_SHIFT)) & LPI2C_SCFGR1_RXCFG_MASK) +#define LPI2C_SCFGR1_IGNACK_MASK (0x1000U) +#define LPI2C_SCFGR1_IGNACK_SHIFT (12U) +#define LPI2C_SCFGR1_IGNACK(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_IGNACK_SHIFT)) & LPI2C_SCFGR1_IGNACK_MASK) +#define LPI2C_SCFGR1_HSMEN_MASK (0x2000U) +#define LPI2C_SCFGR1_HSMEN_SHIFT (13U) +#define LPI2C_SCFGR1_HSMEN(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_HSMEN_SHIFT)) & LPI2C_SCFGR1_HSMEN_MASK) +#define LPI2C_SCFGR1_ADDRCFG_MASK (0x70000U) +#define LPI2C_SCFGR1_ADDRCFG_SHIFT (16U) +#define LPI2C_SCFGR1_ADDRCFG(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR1_ADDRCFG_SHIFT)) & LPI2C_SCFGR1_ADDRCFG_MASK) + +/*! @name SCFGR2 - Slave Configuration Register 2 */ +#define LPI2C_SCFGR2_CLKHOLD_MASK (0xFU) +#define LPI2C_SCFGR2_CLKHOLD_SHIFT (0U) +#define LPI2C_SCFGR2_CLKHOLD(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR2_CLKHOLD_SHIFT)) & LPI2C_SCFGR2_CLKHOLD_MASK) +#define LPI2C_SCFGR2_DATAVD_MASK (0x3F00U) +#define LPI2C_SCFGR2_DATAVD_SHIFT (8U) +#define LPI2C_SCFGR2_DATAVD(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR2_DATAVD_SHIFT)) & LPI2C_SCFGR2_DATAVD_MASK) +#define LPI2C_SCFGR2_FILTSCL_MASK (0xF0000U) +#define LPI2C_SCFGR2_FILTSCL_SHIFT (16U) +#define LPI2C_SCFGR2_FILTSCL(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR2_FILTSCL_SHIFT)) & LPI2C_SCFGR2_FILTSCL_MASK) +#define LPI2C_SCFGR2_FILTSDA_MASK (0xF000000U) +#define LPI2C_SCFGR2_FILTSDA_SHIFT (24U) +#define LPI2C_SCFGR2_FILTSDA(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SCFGR2_FILTSDA_SHIFT)) & LPI2C_SCFGR2_FILTSDA_MASK) + +/*! @name SAMR - Slave Address Match Register */ +#define LPI2C_SAMR_ADDR0_MASK (0x7FEU) +#define LPI2C_SAMR_ADDR0_SHIFT (1U) +#define LPI2C_SAMR_ADDR0(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SAMR_ADDR0_SHIFT)) & LPI2C_SAMR_ADDR0_MASK) +#define LPI2C_SAMR_ADDR1_MASK (0x7FE0000U) +#define LPI2C_SAMR_ADDR1_SHIFT (17U) +#define LPI2C_SAMR_ADDR1(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SAMR_ADDR1_SHIFT)) & LPI2C_SAMR_ADDR1_MASK) + +/*! @name SASR - Slave Address Status Register */ +#define LPI2C_SASR_RADDR_MASK (0x7FFU) +#define LPI2C_SASR_RADDR_SHIFT (0U) +#define LPI2C_SASR_RADDR(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SASR_RADDR_SHIFT)) & LPI2C_SASR_RADDR_MASK) +#define LPI2C_SASR_ANV_MASK (0x4000U) +#define LPI2C_SASR_ANV_SHIFT (14U) +#define LPI2C_SASR_ANV(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SASR_ANV_SHIFT)) & LPI2C_SASR_ANV_MASK) + +/*! @name STAR - Slave Transmit ACK Register */ +#define LPI2C_STAR_TXNACK_MASK (0x1U) +#define LPI2C_STAR_TXNACK_SHIFT (0U) +#define LPI2C_STAR_TXNACK(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_STAR_TXNACK_SHIFT)) & LPI2C_STAR_TXNACK_MASK) + +/*! @name STDR - Slave Transmit Data Register */ +#define LPI2C_STDR_DATA_MASK (0xFFU) +#define LPI2C_STDR_DATA_SHIFT (0U) +#define LPI2C_STDR_DATA(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_STDR_DATA_SHIFT)) & LPI2C_STDR_DATA_MASK) + +/*! @name SRDR - Slave Receive Data Register */ +#define LPI2C_SRDR_DATA_MASK (0xFFU) +#define LPI2C_SRDR_DATA_SHIFT (0U) +#define LPI2C_SRDR_DATA(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SRDR_DATA_SHIFT)) & LPI2C_SRDR_DATA_MASK) +#define LPI2C_SRDR_RXEMPTY_MASK (0x4000U) +#define LPI2C_SRDR_RXEMPTY_SHIFT (14U) +#define LPI2C_SRDR_RXEMPTY(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SRDR_RXEMPTY_SHIFT)) & LPI2C_SRDR_RXEMPTY_MASK) +#define LPI2C_SRDR_SOF_MASK (0x8000U) +#define LPI2C_SRDR_SOF_SHIFT (15U) +#define LPI2C_SRDR_SOF(x) (((uint32_t)(((uint32_t)(x)) << LPI2C_SRDR_SOF_SHIFT)) & LPI2C_SRDR_SOF_MASK) + +#endif /* __ASM_ARCH_IMX_I2C_H__ */ diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 39f62daf5d7..8ac7aaf2d23 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -109,6 +109,12 @@ config SYS_I2C_INTEL the I2C API meaning that any I2C operations will immediately fail for now. +config SYS_I2C_IMX_LPI2C + bool "NXP i.MX LPI2C driver" + depends on ARCH_MX7ULP + help + Add support for the NXP i.MX LPI2C driver. + config SYS_I2C_MXC bool "NXP i.MX I2C driver" depends on MX6 diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 7c86198863c..446af225bc1 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o obj-$(CONFIG_SYS_I2C_FTI2C010) += fti2c010.o obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o obj-$(CONFIG_SYS_I2C_INTEL) += intel_i2c.o +obj-$(CONFIG_SYS_I2C_IMX_LPI2C) += imx_lpi2c.o obj-$(CONFIG_SYS_I2C_KONA) += kona_i2c.o obj-$(CONFIG_SYS_I2C_LPC32XX) += lpc32xx_i2c.o obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o diff --git a/drivers/i2c/imx_lpi2c.c b/drivers/i2c/imx_lpi2c.c new file mode 100644 index 00000000000..f792d4432da --- /dev/null +++ b/drivers/i2c/imx_lpi2c.c @@ -0,0 +1,462 @@ +/* + * Copyright 2016 Freescale Semiconductors, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; +#define LPI2C_FIFO_SIZE 4 +#define LPI2C_TIMEOUT_MS 100 + +/* Weak linked function for overridden by some SoC power function */ +int __weak init_i2c_power(unsigned i2c_num) +{ + return 0; +} + +static int imx_lpci2c_check_busy_bus(struct udevice *bus) +{ + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus); + lpi2c_status_t result = LPI2C_SUCESS; + u32 status; + + status = readl(®s->msr); + + if ((status & LPI2C_MSR_BBF_MASK) && !(status & LPI2C_MSR_MBF_MASK)) + result = LPI2C_BUSY; + + return result; +} + +static int imx_lpci2c_check_clear_error(struct udevice *bus) +{ + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus); + lpi2c_status_t result = LPI2C_SUCESS; + u32 val, status; + + status = readl(®s->msr); + /* errors to check for */ + status &= LPI2C_MSR_NDF_MASK | LPI2C_MSR_ALF_MASK | + LPI2C_MSR_FEF_MASK | LPI2C_MSR_PLTF_MASK; + + if (status) { + if (status & LPI2C_MSR_PLTF_MASK) + result = LPI2C_PIN_LOW_TIMEOUT_ERR; + else if (status & LPI2C_MSR_ALF_MASK) + result = LPI2C_ARB_LOST_ERR; + else if (status & LPI2C_MSR_NDF_MASK) + result = LPI2C_NAK_ERR; + else if (status & LPI2C_MSR_FEF_MASK) + result = LPI2C_FIFO_ERR; + + /* clear status flags */ + writel(0x7f00, ®s->msr); + /* reset fifos */ + val = readl(®s->mcr); + val |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK; + writel(val, ®s->mcr); + } + + return result; +} + +static int bus_i2c_wait_for_tx_ready(struct udevice *bus) +{ + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus); + lpi2c_status_t result = LPI2C_SUCESS; + u32 txcount = 0; + ulong start_time = get_timer(0); + + do { + txcount = LPI2C_MFSR_TXCOUNT(readl(®s->mfsr)); + txcount = LPI2C_FIFO_SIZE - txcount; + result = imx_lpci2c_check_clear_error(bus); + if (result) { + debug("i2c: wait for tx ready: result 0x%x\n", result); + return result; + } + if (get_timer(start_time) > LPI2C_TIMEOUT_MS) { + debug("i2c: wait for tx ready: timeout\n"); + return -1; + } + } while (!txcount); + + return result; +} + +static int bus_i2c_send(struct udevice *bus, u8 *txbuf, int len) +{ + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus); + lpi2c_status_t result = LPI2C_SUCESS; + + /* empty tx */ + if (!len) + return result; + + while (len--) { + result = bus_i2c_wait_for_tx_ready(bus); + if (result) { + debug("i2c: send wait fot tx ready: %d\n", result); + return result; + } + writel(*txbuf++, ®s->mtdr); + } + + return result; +} + +static int bus_i2c_receive(struct udevice *bus, u8 *rxbuf, int len) +{ + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus); + lpi2c_status_t result = LPI2C_SUCESS; + u32 val; + ulong start_time = get_timer(0); + + /* empty read */ + if (!len) + return result; + + result = bus_i2c_wait_for_tx_ready(bus); + if (result) { + debug("i2c: receive wait fot tx ready: %d\n", result); + return result; + } + + /* clear all status flags */ + writel(0x7f00, ®s->msr); + /* send receive command */ + val = LPI2C_MTDR_CMD(0x1) | LPI2C_MTDR_DATA(len - 1); + writel(val, ®s->mtdr); + + while (len--) { + do { + result = imx_lpci2c_check_clear_error(bus); + if (result) { + debug("i2c: receive check clear error: %d\n", result); + return result; + } + if (get_timer(start_time) > LPI2C_TIMEOUT_MS) { + debug("i2c: receive mrdr: timeout\n"); + return -1; + } + val = readl(®s->mrdr); + } while (val & LPI2C_MRDR_RXEMPTY_MASK); + *rxbuf++ = LPI2C_MRDR_DATA(val); + } + + return result; +} + +static int bus_i2c_start(struct udevice *bus, u8 addr, u8 dir) +{ + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus); + lpi2c_status_t result = LPI2C_SUCESS; + u32 val; + + result = imx_lpci2c_check_busy_bus(bus); + if (result) { + debug("i2c: start check busy bus: 0x%x\n", result); + return result; + } + /* clear all status flags */ + writel(0x7f00, ®s->msr); + /* turn off auto-stop condition */ + val = readl(®s->mcfgr1) & ~LPI2C_MCFGR1_AUTOSTOP_MASK; + writel(val, ®s->mcfgr1); + /* wait tx fifo ready */ + result = bus_i2c_wait_for_tx_ready(bus); + if (result) { + debug("i2c: start wait for tx ready: 0x%x\n", result); + return result; + } + /* issue start command */ + val = LPI2C_MTDR_CMD(0x4) | (addr << 0x1) | dir; + writel(val, ®s->mtdr); + + return result; +} +static int bus_i2c_stop(struct udevice *bus) +{ + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus); + lpi2c_status_t result = LPI2C_SUCESS; + u32 status; + + result = bus_i2c_wait_for_tx_ready(bus); + if (result) { + debug("i2c: stop wait for tx ready: 0x%x\n", result); + return result; + } + + /* send stop command */ + writel(LPI2C_MTDR_CMD(0x2), ®s->mtdr); + + while (result == LPI2C_SUCESS) { + status = readl(®s->msr); + result = imx_lpci2c_check_clear_error(bus); + /* stop detect flag */ + if (status & LPI2C_MSR_SDF_MASK) { + /* clear stop flag */ + status &= LPI2C_MSR_SDF_MASK; + writel(status, ®s->msr); + break; + } + } + + return result; +} + +static int bus_i2c_read(struct udevice *bus, u32 chip, u8 *buf, int len) +{ + lpi2c_status_t result = LPI2C_SUCESS; + + result = bus_i2c_start(bus, chip, 1); + if (result) + return result; + result = bus_i2c_receive(bus, buf, len); + if (result) + return result; + result = bus_i2c_stop(bus); + if (result) + return result; + + return result; +} + +static int bus_i2c_write(struct udevice *bus, u32 chip, u8 *buf, int len) +{ + lpi2c_status_t result = LPI2C_SUCESS; + + result = bus_i2c_start(bus, chip, 0); + if (result) + return result; + result = bus_i2c_send(bus, buf, len); + if (result) + return result; + result = bus_i2c_stop(bus); + if (result) + return result; + + return result; +} + + +static int bus_i2c_set_bus_speed(struct udevice *bus, int speed) +{ + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus); + u32 val; + u32 preescale = 0, best_pre = 0, clkhi = 0; + u32 best_clkhi = 0, abs_error = 0, rate; + u32 error = 0xffffffff; + u32 clock_rate; + bool mode; + int i; + + clock_rate = imx_get_i2cclk(bus->seq + 4); + if (!clock_rate) + return -EPERM; + + mode = (readl(®s->mcr) & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT; + /* disable master mode */ + val = readl(®s->mcr) & ~LPI2C_MCR_MEN_MASK; + writel(val | LPI2C_MCR_MEN(0), ®s->mcr); + + for (preescale = 1; (preescale <= 128) && + (error != 0); preescale = 2 * preescale) { + for (clkhi = 1; clkhi < 32; clkhi++) { + if (clkhi == 1) + rate = (clock_rate / preescale) / (1 + 3 + 2 + 2 / preescale); + else + rate = (clock_rate / preescale / (3 * clkhi + 2 + 2 / preescale)); + + abs_error = speed > rate ? speed - rate : rate - speed; + + if (abs_error < error) { + best_pre = preescale; + best_clkhi = clkhi; + error = abs_error; + if (abs_error == 0) + break; + } + } + } + + /* Standard, fast, fast mode plus and ultra-fast transfers. */ + val = LPI2C_MCCR0_CLKHI(best_clkhi); + if (best_clkhi < 2) + val |= LPI2C_MCCR0_CLKLO(3) | LPI2C_MCCR0_SETHOLD(2) | LPI2C_MCCR0_DATAVD(1); + else + val |= LPI2C_MCCR0_CLKLO(2 * best_clkhi) | LPI2C_MCCR0_SETHOLD(best_clkhi) | + LPI2C_MCCR0_DATAVD(best_clkhi / 2); + writel(val, ®s->mccr0); + + for (i = 0; i < 8; i++) { + if (best_pre == (1 << i)) { + best_pre = i; + break; + } + } + + val = readl(®s->mcfgr1) & ~LPI2C_MCFGR1_PRESCALE_MASK; + writel(val | LPI2C_MCFGR1_PRESCALE(best_pre), ®s->mcfgr1); + + if (mode) { + val = readl(®s->mcr) & ~LPI2C_MCR_MEN_MASK; + writel(val | LPI2C_MCR_MEN(1), ®s->mcr); + } + + return 0; +} + +static int bus_i2c_init(struct udevice *bus, int speed) +{ + struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus); + u32 val; + int ret; + + /* reset peripheral */ + writel(LPI2C_MCR_RST_MASK, ®s->mcr); + writel(0x0, ®s->mcr); + /* Disable Dozen mode */ + writel(LPI2C_MCR_DBGEN(0) | LPI2C_MCR_DOZEN(1), ®s->mcr); + /* host request disable, active high, external pin */ + val = readl(®s->mcfgr0); + val &= (~(LPI2C_MCFGR0_HREN_MASK | LPI2C_MCFGR0_HRPOL_MASK | + LPI2C_MCFGR0_HRSEL_MASK)); + val |= LPI2C_MCFGR0_HRPOL(0x1); + writel(val, ®s->mcfgr0); + /* pincfg and ignore ack */ + val = readl(®s->mcfgr1); + val &= ~(LPI2C_MCFGR1_PINCFG_MASK | LPI2C_MCFGR1_IGNACK_MASK); + val |= LPI2C_MCFGR1_PINCFG(0x0); /* 2 pin open drain */ + val |= LPI2C_MCFGR1_IGNACK(0x0); /* ignore nack */ + writel(val, ®s->mcfgr1); + + ret = bus_i2c_set_bus_speed(bus, speed); + + /* enable lpi2c in master mode */ + val = readl(®s->mcr) & ~LPI2C_MCR_MEN_MASK; + writel(val | LPI2C_MCR_MEN(1), ®s->mcr); + + debug("i2c : controller bus %d, speed %d:\n", bus->seq, speed); + + return ret; +} + +static int imx_lpi2c_probe_chip(struct udevice *bus, u32 chip, + u32 chip_flags) +{ + lpi2c_status_t result = LPI2C_SUCESS; + + result = bus_i2c_start(bus, chip, 0); + if (result) { + bus_i2c_stop(bus); + bus_i2c_init(bus, 100000); + return result; + } + + result = bus_i2c_stop(bus); + if (result) { + bus_i2c_init(bus, 100000); + return -result; + } + + return result; +} + +static int imx_lpi2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) +{ + int ret = 0; + + for (; nmsgs > 0; nmsgs--, msg++) { + debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len); + if (msg->flags & I2C_M_RD) + ret = bus_i2c_read(bus, msg->addr, msg->buf, + msg->len); + else { + ret = bus_i2c_write(bus, msg->addr, msg->buf, + msg->len); + if (ret) + break; + } + } + + if (ret) + debug("i2c_write: error sending\n"); + + return ret; +} + +static int imx_lpi2c_set_bus_speed(struct udevice *bus, unsigned int speed) +{ + return bus_i2c_set_bus_speed(bus, speed); +} + +static int imx_lpi2c_probe(struct udevice *bus) +{ + struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus); + fdt_addr_t addr; + int ret; + + i2c_bus->driver_data = dev_get_driver_data(bus); + + addr = dev_get_addr(bus); + if (addr == FDT_ADDR_T_NONE) + return -ENODEV; + + i2c_bus->base = addr; + i2c_bus->index = bus->seq; + i2c_bus->bus = bus; + + /* power up i2c resource */ + ret = init_i2c_power(bus->seq + 4); + if (ret) { + debug("init_i2c_power err = %d\n", ret); + return ret; + } + + /* Enable clk, only i2c4-7 can be handled by A7 core */ + ret = enable_i2c_clk(1, bus->seq + 4); + if (ret < 0) + return ret; + + ret = bus_i2c_init(bus, 100000); + if (ret < 0) + return ret; + + debug("i2c : controller bus %d at %lu , speed %d: ", + bus->seq, i2c_bus->base, + i2c_bus->speed); + + return 0; +} + +static const struct dm_i2c_ops imx_lpi2c_ops = { + .xfer = imx_lpi2c_xfer, + .probe_chip = imx_lpi2c_probe_chip, + .set_bus_speed = imx_lpi2c_set_bus_speed, +}; + +static const struct udevice_id imx_lpi2c_ids[] = { + { .compatible = "fsl,imx7ulp-lpi2c", }, + {} +}; + +U_BOOT_DRIVER(imx_lpi2c) = { + .name = "imx_lpi2c", + .id = UCLASS_I2C, + .of_match = imx_lpi2c_ids, + .probe = imx_lpi2c_probe, + .priv_auto_alloc_size = sizeof(struct imx_lpi2c_bus), + .ops = &imx_lpi2c_ops, +}; -- cgit v1.3.1 From c40d612b1a6e1c63f27089d1d8fa3016164cacdb Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 22 Feb 2017 16:21:51 +0800 Subject: serial: lpuart: restructure lpuart driver Drop CONFIG_LPUART_32B_REG. Move the register structure to a common file include/fsl_lpuart.h Define lpuart_serial_platdata structure which includes the reg base and flags. For 32Bit register access, use lpuart_read32/lpuart_write32 which handles big/little endian. For 8Bit register access, still use the orignal code. Signed-off-by: Peng Fan Reviewed-by : Stefano Babic Cc: Bhuvanchandra DV Cc: York Sun Cc: Shaohui Xie Cc: Alison Wang --- arch/arm/cpu/armv7/vf610/generic.c | 5 + .../arm/include/asm/arch-fsl-layerscape/imx-regs.h | 42 ---- arch/arm/include/asm/arch-ls102xa/imx-regs.h | 40 --- arch/arm/include/asm/arch-vf610/clock.h | 1 + arch/arm/include/asm/arch-vf610/imx-regs.h | 28 --- drivers/serial/serial_lpuart.c | 267 +++++++++++---------- 6 files changed, 148 insertions(+), 235 deletions(-) (limited to 'drivers') diff --git a/arch/arm/cpu/armv7/vf610/generic.c b/arch/arm/cpu/armv7/vf610/generic.c index 50eb0c6b97c..0328096afd0 100644 --- a/arch/arm/cpu/armv7/vf610/generic.c +++ b/arch/arm/cpu/armv7/vf610/generic.c @@ -204,6 +204,11 @@ static u32 get_dspi_clk(void) return get_ipg_clk(); } +u32 get_lpuart_clk(void) +{ + return get_uart_clk(); +} + unsigned int mxc_get_clock(enum mxc_clock clk) { switch (clk) { diff --git a/arch/arm/include/asm/arch-fsl-layerscape/imx-regs.h b/arch/arm/include/asm/arch-fsl-layerscape/imx-regs.h index 57e417b9e08..b0e58ca807f 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/imx-regs.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/imx-regs.h @@ -10,46 +10,4 @@ #define I2C_QUIRK_REG /* enable 8-bit driver */ -#ifdef CONFIG_FSL_LPUART -#ifdef CONFIG_LPUART_32B_REG -struct lpuart_fsl { - u32 baud; - u32 stat; - u32 ctrl; - u32 data; - u32 match; - u32 modir; - u32 fifo; - u32 water; -}; -#else -struct lpuart_fsl { - u8 ubdh; - u8 ubdl; - u8 uc1; - u8 uc2; - u8 us1; - u8 us2; - u8 uc3; - u8 ud; - u8 uma1; - u8 uma2; - u8 uc4; - u8 uc5; - u8 ued; - u8 umodem; - u8 uir; - u8 reserved; - u8 upfifo; - u8 ucfifo; - u8 usfifo; - u8 utwfifo; - u8 utcfifo; - u8 urwfifo; - u8 urcfifo; - u8 rsvd[28]; -}; -#endif -#endif /* CONFIG_FSL_LPUART */ - #endif /* __ASM_ARCH_FSL_LAYERSCAPE_IMX_REGS_H__ */ diff --git a/arch/arm/include/asm/arch-ls102xa/imx-regs.h b/arch/arm/include/asm/arch-ls102xa/imx-regs.h index f9cd75b021f..7190f3d08e3 100644 --- a/arch/arm/include/asm/arch-ls102xa/imx-regs.h +++ b/arch/arm/include/asm/arch-ls102xa/imx-regs.h @@ -10,44 +10,4 @@ #define I2C_QUIRK_REG /* enable 8-bit driver */ -#ifdef CONFIG_LPUART_32B_REG -struct lpuart_fsl { - u32 baud; - u32 stat; - u32 ctrl; - u32 data; - u32 match; - u32 modir; - u32 fifo; - u32 water; -}; -#else -struct lpuart_fsl { - u8 ubdh; - u8 ubdl; - u8 uc1; - u8 uc2; - u8 us1; - u8 us2; - u8 uc3; - u8 ud; - u8 uma1; - u8 uma2; - u8 uc4; - u8 uc5; - u8 ued; - u8 umodem; - u8 uir; - u8 reserved; - u8 upfifo; - u8 ucfifo; - u8 usfifo; - u8 utwfifo; - u8 utcfifo; - u8 urwfifo; - u8 urcfifo; - u8 rsvd[28]; -}; -#endif - #endif /* __ASM_ARCH_IMX_REGS_H__ */ diff --git a/arch/arm/include/asm/arch-vf610/clock.h b/arch/arm/include/asm/arch-vf610/clock.h index e5a5c6d28f3..c5ba240c76e 100644 --- a/arch/arm/include/asm/arch-vf610/clock.h +++ b/arch/arm/include/asm/arch-vf610/clock.h @@ -22,6 +22,7 @@ enum mxc_clock { void enable_ocotp_clk(unsigned char enable); unsigned int mxc_get_clock(enum mxc_clock clk); +u32 get_lpuart_clk(void); #define imx_get_fecclk() mxc_get_clock(MXC_FEC_CLK) diff --git a/arch/arm/include/asm/arch-vf610/imx-regs.h b/arch/arm/include/asm/arch-vf610/imx-regs.h index 97583234331..cac68efde2e 100644 --- a/arch/arm/include/asm/arch-vf610/imx-regs.h +++ b/arch/arm/include/asm/arch-vf610/imx-regs.h @@ -429,34 +429,6 @@ struct fuse_bank4_regs { u32 rsvd7[3]; }; -/* UART */ -struct lpuart_fsl { - u8 ubdh; - u8 ubdl; - u8 uc1; - u8 uc2; - u8 us1; - u8 us2; - u8 uc3; - u8 ud; - u8 uma1; - u8 uma2; - u8 uc4; - u8 uc5; - u8 ued; - u8 umodem; - u8 uir; - u8 reserved; - u8 upfifo; - u8 ucfifo; - u8 usfifo; - u8 utwfifo; - u8 utcfifo; - u8 urwfifo; - u8 urcfifo; - u8 rsvd[28]; -}; - /* MSCM Interrupt Router */ struct mscm_ir { u32 ircp0ir; diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c index beb42431245..3f030a622f2 100644 --- a/drivers/serial/serial_lpuart.c +++ b/drivers/serial/serial_lpuart.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -48,14 +49,56 @@ DECLARE_GLOBAL_DATA_PTR; +#define LPUART_FLAG_REGMAP_32BIT_REG BIT(0) +#define LPUART_FLAG_REGMAP_ENDIAN_BIG BIT(1) + struct lpuart_serial_platdata { - struct lpuart_fsl *reg; + void *reg; + ulong flags; }; -#ifndef CONFIG_LPUART_32B_REG -static void _lpuart_serial_setbrg(struct lpuart_fsl *base, int baudrate) +static void lpuart_read32(u32 flags, u32 *addr, u32 *val) +{ + if (flags & LPUART_FLAG_REGMAP_32BIT_REG) { + if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG) + *(u32 *)val = in_be32(addr); + else + *(u32 *)val = in_le32(addr); + } +} + +static void lpuart_write32(u32 flags, u32 *addr, u32 val) +{ + if (flags & LPUART_FLAG_REGMAP_32BIT_REG) { + if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG) + out_be32(addr, val); + else + out_le32(addr, val); + } +} + + +#ifndef CONFIG_SYS_CLK_FREQ +#define CONFIG_SYS_CLK_FREQ 0 +#endif + +u32 __weak get_lpuart_clk(void) { - u32 clk = mxc_get_clock(MXC_UART_CLK); + return CONFIG_SYS_CLK_FREQ; +} + +static bool is_lpuart32(struct udevice *dev) +{ + struct lpuart_serial_platdata *plat = dev->platdata; + + return plat->flags & LPUART_FLAG_REGMAP_32BIT_REG; +} + +static void _lpuart_serial_setbrg(struct lpuart_serial_platdata *plat, + int baudrate) +{ + struct lpuart_fsl *base = plat->reg; + u32 clk = get_lpuart_clk(); u16 sbr; sbr = (u16)(clk / (16 * baudrate)); @@ -65,8 +108,9 @@ static void _lpuart_serial_setbrg(struct lpuart_fsl *base, int baudrate) __raw_writeb(sbr & 0xff, &base->ubdl); } -static int _lpuart_serial_getc(struct lpuart_fsl *base) +static int _lpuart_serial_getc(struct lpuart_serial_platdata *plat) { + struct lpuart_fsl *base = plat->reg; while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR))) WATCHDOG_RESET(); @@ -75,8 +119,11 @@ static int _lpuart_serial_getc(struct lpuart_fsl *base) return __raw_readb(&base->ud); } -static void _lpuart_serial_putc(struct lpuart_fsl *base, const char c) +static void _lpuart_serial_putc(struct lpuart_serial_platdata *plat, + const char c) { + struct lpuart_fsl *base = plat->reg; + while (!(__raw_readb(&base->us1) & US1_TDRE)) WATCHDOG_RESET(); @@ -84,8 +131,10 @@ static void _lpuart_serial_putc(struct lpuart_fsl *base, const char c) } /* Test whether a character is in the RX buffer */ -static int _lpuart_serial_tstc(struct lpuart_fsl *base) +static int _lpuart_serial_tstc(struct lpuart_serial_platdata *plat) { + struct lpuart_fsl *base = plat->reg; + if (__raw_readb(&base->urcfifo) == 0) return 0; @@ -96,8 +145,9 @@ static int _lpuart_serial_tstc(struct lpuart_fsl *base) * Initialise the serial port with the given baudrate. The settings * are always 8 data bits, no parity, 1 stop bit, no start bits. */ -static int _lpuart_serial_init(struct lpuart_fsl *base) +static int _lpuart_serial_init(struct lpuart_serial_platdata *plat) { + struct lpuart_fsl *base = (struct lpuart_fsl *)plat->reg; u8 ctrl; ctrl = __raw_readb(&base->uc2); @@ -115,101 +165,71 @@ static int _lpuart_serial_init(struct lpuart_fsl *base) __raw_writeb(CFIFO_TXFLUSH | CFIFO_RXFLUSH, &base->ucfifo); /* provide data bits, parity, stop bit, etc */ - _lpuart_serial_setbrg(base, gd->baudrate); + _lpuart_serial_setbrg(plat, gd->baudrate); __raw_writeb(UC2_RE | UC2_TE, &base->uc2); return 0; } -static int lpuart_serial_setbrg(struct udevice *dev, int baudrate) -{ - struct lpuart_serial_platdata *plat = dev->platdata; - struct lpuart_fsl *reg = plat->reg; - - _lpuart_serial_setbrg(reg, baudrate); - - return 0; -} - -static int lpuart_serial_getc(struct udevice *dev) -{ - struct lpuart_serial_platdata *plat = dev->platdata; - struct lpuart_fsl *reg = plat->reg; - - return _lpuart_serial_getc(reg); -} - -static int lpuart_serial_putc(struct udevice *dev, const char c) -{ - struct lpuart_serial_platdata *plat = dev->platdata; - struct lpuart_fsl *reg = plat->reg; - - _lpuart_serial_putc(reg, c); - - return 0; -} - -static int lpuart_serial_pending(struct udevice *dev, bool input) -{ - struct lpuart_serial_platdata *plat = dev->platdata; - struct lpuart_fsl *reg = plat->reg; - - if (input) - return _lpuart_serial_tstc(reg); - else - return __raw_readb(®->us1) & US1_TDRE ? 0 : 1; -} - -static int lpuart_serial_probe(struct udevice *dev) -{ - struct lpuart_serial_platdata *plat = dev->platdata; - struct lpuart_fsl *reg = plat->reg; - - return _lpuart_serial_init(reg); -} -#else - -u32 __weak get_lpuart_clk(void) -{ - return CONFIG_SYS_CLK_FREQ; -} - -static void _lpuart32_serial_setbrg(struct lpuart_fsl *base, int baudrate) +static void _lpuart32_serial_setbrg(struct lpuart_serial_platdata *plat, + int baudrate) { + struct lpuart_fsl_reg32 *base = plat->reg; u32 clk = get_lpuart_clk(); u32 sbr; sbr = (clk / (16 * baudrate)); /* place adjustment later - n/32 BRFA */ - out_be32(&base->baud, sbr); + lpuart_write32(plat->flags, &base->baud, sbr); } -static int _lpuart32_serial_getc(struct lpuart_fsl *base) +static int _lpuart32_serial_getc(struct lpuart_serial_platdata *plat) { + struct lpuart_fsl_reg32 *base = plat->reg; u32 stat; - while (((stat = in_be32(&base->stat)) & STAT_RDRF) == 0) { - out_be32(&base->stat, STAT_FLAGS); + lpuart_read32(plat->flags, &base->stat, &stat); + while ((stat & STAT_RDRF) == 0) { + lpuart_write32(plat->flags, &base->stat, STAT_FLAGS); WATCHDOG_RESET(); + lpuart_read32(plat->flags, &base->stat, &stat); } - return in_be32(&base->data) & 0x3ff; + /* Reuse stat */ + lpuart_read32(plat->flags, &base->data, &stat); + + return stat & 0x3ff; } -static void _lpuart32_serial_putc(struct lpuart_fsl *base, const char c) +static void _lpuart32_serial_putc(struct lpuart_serial_platdata *plat, + const char c) { - while (!(in_be32(&base->stat) & STAT_TDRE)) + struct lpuart_fsl_reg32 *base = plat->reg; + u32 stat; + + while (true) { + lpuart_read32(plat->flags, &base->stat, &stat); + + if ((stat & STAT_TDRE)) + break; + WATCHDOG_RESET(); + } - out_be32(&base->data, c); + lpuart_write32(plat->flags, &base->data, c); } /* Test whether a character is in the RX buffer */ -static int _lpuart32_serial_tstc(struct lpuart_fsl *base) +static int _lpuart32_serial_tstc(struct lpuart_serial_platdata *plat) { - if ((in_be32(&base->water) >> 24) == 0) + struct lpuart_fsl_reg32 *base = plat->reg; + u32 water; + + lpuart_read32(plat->flags, &base->water, &water); + + if ((water >> 24) == 0) return 0; return 1; @@ -219,75 +239,94 @@ static int _lpuart32_serial_tstc(struct lpuart_fsl *base) * Initialise the serial port with the given baudrate. The settings * are always 8 data bits, no parity, 1 stop bit, no start bits. */ -static int _lpuart32_serial_init(struct lpuart_fsl *base) +static int _lpuart32_serial_init(struct lpuart_serial_platdata *plat) { - u8 ctrl; + struct lpuart_fsl_reg32 *base = (struct lpuart_fsl_reg32 *)plat->reg; + u32 ctrl; - ctrl = in_be32(&base->ctrl); + lpuart_read32(plat->flags, &base->ctrl, &ctrl); ctrl &= ~CTRL_RE; ctrl &= ~CTRL_TE; - out_be32(&base->ctrl, ctrl); + lpuart_write32(plat->flags, &base->ctrl, ctrl); - out_be32(&base->modir, 0); - out_be32(&base->fifo, ~(FIFO_TXFE | FIFO_RXFE)); + lpuart_write32(plat->flags, &base->modir, 0); + lpuart_write32(plat->flags, &base->fifo, ~(FIFO_TXFE | FIFO_RXFE)); - out_be32(&base->match, 0); + lpuart_write32(plat->flags, &base->match, 0); /* provide data bits, parity, stop bit, etc */ - _lpuart32_serial_setbrg(base, gd->baudrate); + _lpuart32_serial_setbrg(plat, gd->baudrate); - out_be32(&base->ctrl, CTRL_RE | CTRL_TE); + lpuart_write32(plat->flags, &base->ctrl, CTRL_RE | CTRL_TE); return 0; } -static int lpuart32_serial_setbrg(struct udevice *dev, int baudrate) +static int lpuart_serial_setbrg(struct udevice *dev, int baudrate) { struct lpuart_serial_platdata *plat = dev->platdata; - struct lpuart_fsl *reg = plat->reg; - _lpuart32_serial_setbrg(reg, baudrate); + if (is_lpuart32(dev)) + _lpuart32_serial_setbrg(plat, baudrate); + else + _lpuart_serial_setbrg(plat, baudrate); return 0; } -static int lpuart32_serial_getc(struct udevice *dev) +static int lpuart_serial_getc(struct udevice *dev) { struct lpuart_serial_platdata *plat = dev->platdata; - struct lpuart_fsl *reg = plat->reg; - return _lpuart32_serial_getc(reg); + if (is_lpuart32(dev)) + return _lpuart32_serial_getc(plat); + + return _lpuart_serial_getc(plat); } -static int lpuart32_serial_putc(struct udevice *dev, const char c) +static int lpuart_serial_putc(struct udevice *dev, const char c) { struct lpuart_serial_platdata *plat = dev->platdata; - struct lpuart_fsl *reg = plat->reg; - _lpuart32_serial_putc(reg, c); + if (is_lpuart32(dev)) + _lpuart32_serial_putc(plat, c); + else + _lpuart_serial_putc(plat, c); return 0; } -static int lpuart32_serial_pending(struct udevice *dev, bool input) +static int lpuart_serial_pending(struct udevice *dev, bool input) { struct lpuart_serial_platdata *plat = dev->platdata; struct lpuart_fsl *reg = plat->reg; + struct lpuart_fsl_reg32 *reg32 = plat->reg; + u32 stat; + + if (is_lpuart32(dev)) { + if (input) { + return _lpuart32_serial_tstc(plat); + } else { + lpuart_read32(plat->flags, ®32->stat, &stat); + return stat & STAT_TDRE ? 0 : 1; + } + } if (input) - return _lpuart32_serial_tstc(reg); + return _lpuart_serial_tstc(plat); else - return in_be32(®->stat) & STAT_TDRE ? 0 : 1; + return __raw_readb(®->us1) & US1_TDRE ? 0 : 1; } -static int lpuart32_serial_probe(struct udevice *dev) +static int lpuart_serial_probe(struct udevice *dev) { struct lpuart_serial_platdata *plat = dev->platdata; - struct lpuart_fsl *reg = plat->reg; - return _lpuart32_serial_init(reg); + if (is_lpuart32(dev)) + return _lpuart32_serial_init(plat); + else + return _lpuart_serial_init(plat); } -#endif /* CONFIG_LPUART_32B_REG */ static int lpuart_serial_ofdata_to_platdata(struct udevice *dev) { @@ -298,12 +337,12 @@ static int lpuart_serial_ofdata_to_platdata(struct udevice *dev) if (addr == FDT_ADDR_T_NONE) return -EINVAL; - plat->reg = (struct lpuart_fsl *)addr; + plat->reg = (void *)addr; + plat->flags = dev_get_driver_data(dev); return 0; } -#ifndef CONFIG_LPUART_32B_REG static const struct dm_serial_ops lpuart_serial_ops = { .putc = lpuart_serial_putc, .pending = lpuart_serial_pending, @@ -312,7 +351,9 @@ static const struct dm_serial_ops lpuart_serial_ops = { }; static const struct udevice_id lpuart_serial_ids[] = { - { .compatible = "fsl,vf610-lpuart" }, + { .compatible = "fsl,ls1021a-lpuart", .data = + LPUART_FLAG_REGMAP_32BIT_REG | LPUART_FLAG_REGMAP_ENDIAN_BIG }, + { .compatible = "fsl,vf610-lpuart"}, { } }; @@ -326,27 +367,3 @@ U_BOOT_DRIVER(serial_lpuart) = { .ops = &lpuart_serial_ops, .flags = DM_FLAG_PRE_RELOC, }; -#else /* CONFIG_LPUART_32B_REG */ -static const struct dm_serial_ops lpuart32_serial_ops = { - .putc = lpuart32_serial_putc, - .pending = lpuart32_serial_pending, - .getc = lpuart32_serial_getc, - .setbrg = lpuart32_serial_setbrg, -}; - -static const struct udevice_id lpuart32_serial_ids[] = { - { .compatible = "fsl,ls1021a-lpuart" }, - { } -}; - -U_BOOT_DRIVER(serial_lpuart32) = { - .name = "serial_lpuart32", - .id = UCLASS_SERIAL, - .of_match = lpuart32_serial_ids, - .ofdata_to_platdata = lpuart_serial_ofdata_to_platdata, - .platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata), - .probe = lpuart32_serial_probe, - .ops = &lpuart32_serial_ops, - .flags = DM_FLAG_PRE_RELOC, -}; -#endif /* CONFIG_LPUART_32B_REG */ -- cgit v1.3.1 From 7edf5c45f0d7f78ba370013cf513e3e8356c5202 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 22 Feb 2017 16:21:52 +0800 Subject: serial: lpuart: add i.MX7ULP support Add i.MX7ULP support. The buadrate calculation on i.MX7ULP is different,so add a new setbrg function for i.MX7ULP. Add a enum lpuart_devtype for runtime check for different platforms. Signed-off-by: Peng Fan Cc: Stefano Babic Cc: Bhuvanchandra DV Cc: York Sun Cc: Shaohui Xie Cc: Alison Wang --- drivers/serial/serial_lpuart.c | 113 +++++++++++++++++++++++++++++++++++++---- include/fsl_lpuart.h | 72 ++++++++++++++++++++++++++ 2 files changed, 176 insertions(+), 9 deletions(-) create mode 100644 include/fsl_lpuart.h (limited to 'drivers') diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c index 3f030a622f2..95e002ea4b7 100644 --- a/drivers/serial/serial_lpuart.c +++ b/drivers/serial/serial_lpuart.c @@ -52,8 +52,15 @@ DECLARE_GLOBAL_DATA_PTR; #define LPUART_FLAG_REGMAP_32BIT_REG BIT(0) #define LPUART_FLAG_REGMAP_ENDIAN_BIG BIT(1) +enum lpuart_devtype { + DEV_VF610 = 1, + DEV_LS1021A, + DEV_MX7ULP +}; + struct lpuart_serial_platdata { void *reg; + enum lpuart_devtype devtype; ulong flags; }; @@ -172,6 +179,65 @@ static int _lpuart_serial_init(struct lpuart_serial_platdata *plat) return 0; } +static void _lpuart32_serial_setbrg_7ulp(struct lpuart_serial_platdata *plat, + int baudrate) +{ + struct lpuart_fsl_reg32 *base = plat->reg; + u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp; + u32 clk = get_lpuart_clk(); + + baud_diff = baudrate; + osr = 0; + sbr = 0; + + for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) { + tmp_sbr = (clk / (baudrate * tmp_osr)); + + if (tmp_sbr == 0) + tmp_sbr = 1; + + /*calculate difference in actual buad w/ current values */ + tmp_diff = (clk / (tmp_osr * tmp_sbr)); + tmp_diff = tmp_diff - baudrate; + + /* select best values between sbr and sbr+1 */ + if (tmp_diff > (baudrate - (clk / (tmp_osr * (tmp_sbr + 1))))) { + tmp_diff = baudrate - (clk / (tmp_osr * (tmp_sbr + 1))); + tmp_sbr++; + } + + if (tmp_diff <= baud_diff) { + baud_diff = tmp_diff; + osr = tmp_osr; + sbr = tmp_sbr; + } + } + + /* + * TODO: handle buadrate outside acceptable rate + * if (baudDiff > ((config->baudRate_Bps / 100) * 3)) + * { + * Unacceptable baud rate difference of more than 3% + * return kStatus_LPUART_BaudrateNotSupport; + * } + */ + tmp = in_le32(&base->baud); + + if ((osr > 3) && (osr < 8)) + tmp |= LPUART_BAUD_BOTHEDGE_MASK; + + tmp &= ~LPUART_BAUD_OSR_MASK; + tmp |= LPUART_BAUD_OSR(osr-1); + + tmp &= ~LPUART_BAUD_SBR_MASK; + tmp |= LPUART_BAUD_SBR(sbr); + + /* explicitly disable 10 bit mode & set 1 stop bit */ + tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK); + + out_le32(&base->baud, tmp); +} + static void _lpuart32_serial_setbrg(struct lpuart_serial_platdata *plat, int baudrate) { @@ -188,7 +254,7 @@ static void _lpuart32_serial_setbrg(struct lpuart_serial_platdata *plat, static int _lpuart32_serial_getc(struct lpuart_serial_platdata *plat) { struct lpuart_fsl_reg32 *base = plat->reg; - u32 stat; + u32 stat, val; lpuart_read32(plat->flags, &base->stat, &stat); while ((stat & STAT_RDRF) == 0) { @@ -197,10 +263,15 @@ static int _lpuart32_serial_getc(struct lpuart_serial_platdata *plat) lpuart_read32(plat->flags, &base->stat, &stat); } - /* Reuse stat */ - lpuart_read32(plat->flags, &base->data, &stat); + lpuart_read32(plat->flags, &base->data, &val); - return stat & 0x3ff; + if (plat->devtype & DEV_MX7ULP) { + lpuart_read32(plat->flags, &base->stat, &stat); + if (stat & STAT_OR) + lpuart_write32(plat->flags, &base->stat, STAT_OR); + } + + return val & 0x3ff; } static void _lpuart32_serial_putc(struct lpuart_serial_platdata *plat, @@ -209,6 +280,11 @@ static void _lpuart32_serial_putc(struct lpuart_serial_platdata *plat, struct lpuart_fsl_reg32 *base = plat->reg; u32 stat; + if (plat->devtype & DEV_MX7ULP) { + if (c == '\n') + serial_putc('\r'); + } + while (true) { lpuart_read32(plat->flags, &base->stat, &stat); @@ -254,8 +330,12 @@ static int _lpuart32_serial_init(struct lpuart_serial_platdata *plat) lpuart_write32(plat->flags, &base->match, 0); - /* provide data bits, parity, stop bit, etc */ - _lpuart32_serial_setbrg(plat, gd->baudrate); + if (plat->devtype & DEV_MX7ULP) { + _lpuart32_serial_setbrg_7ulp(plat, gd->baudrate); + } else { + /* provide data bits, parity, stop bit, etc */ + _lpuart32_serial_setbrg(plat, gd->baudrate); + } lpuart_write32(plat->flags, &base->ctrl, CTRL_RE | CTRL_TE); @@ -266,10 +346,14 @@ static int lpuart_serial_setbrg(struct udevice *dev, int baudrate) { struct lpuart_serial_platdata *plat = dev->platdata; - if (is_lpuart32(dev)) - _lpuart32_serial_setbrg(plat, baudrate); - else + if (is_lpuart32(dev)) { + if (plat->devtype & DEV_MX7ULP) + _lpuart32_serial_setbrg_7ulp(plat, baudrate); + else + _lpuart32_serial_setbrg(plat, baudrate); + } else { _lpuart_serial_setbrg(plat, baudrate); + } return 0; } @@ -331,6 +415,8 @@ static int lpuart_serial_probe(struct udevice *dev) static int lpuart_serial_ofdata_to_platdata(struct udevice *dev) { struct lpuart_serial_platdata *plat = dev->platdata; + const void *blob = gd->fdt_blob; + int node = dev->of_offset; fdt_addr_t addr; addr = dev_get_addr(dev); @@ -340,6 +426,13 @@ static int lpuart_serial_ofdata_to_platdata(struct udevice *dev) plat->reg = (void *)addr; plat->flags = dev_get_driver_data(dev); + if (!fdt_node_check_compatible(blob, node, "fsl,ls1021a-lpuart")) + plat->devtype = DEV_LS1021A; + else if (!fdt_node_check_compatible(blob, node, "fsl,imx7ulp-lpuart")) + plat->devtype = DEV_MX7ULP; + else if (!fdt_node_check_compatible(blob, node, "fsl,vf610-lpuart")) + plat->devtype = DEV_VF610; + return 0; } @@ -353,6 +446,8 @@ static const struct dm_serial_ops lpuart_serial_ops = { static const struct udevice_id lpuart_serial_ids[] = { { .compatible = "fsl,ls1021a-lpuart", .data = LPUART_FLAG_REGMAP_32BIT_REG | LPUART_FLAG_REGMAP_ENDIAN_BIG }, + { .compatible = "fsl,imx7ulp-lpuart", + .data = LPUART_FLAG_REGMAP_32BIT_REG }, { .compatible = "fsl,vf610-lpuart"}, { } }; diff --git a/include/fsl_lpuart.h b/include/fsl_lpuart.h new file mode 100644 index 00000000000..4643ee79ee9 --- /dev/null +++ b/include/fsl_lpuart.h @@ -0,0 +1,72 @@ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#ifdef CONFIG_ARCH_MX7ULP +struct lpuart_fsl_reg32 { + u32 verid; + u32 param; + u32 global; + u32 pincfg; + u32 baud; + u32 stat; + u32 ctrl; + u32 data; + u32 match; + u32 modir; + u32 fifo; + u32 water; +}; +#else +struct lpuart_fsl_reg32 { + u32 baud; + u32 stat; + u32 ctrl; + u32 data; + u32 match; + u32 modir; + u32 fifo; + u32 water; +}; +#endif + +struct lpuart_fsl { + u8 ubdh; + u8 ubdl; + u8 uc1; + u8 uc2; + u8 us1; + u8 us2; + u8 uc3; + u8 ud; + u8 uma1; + u8 uma2; + u8 uc4; + u8 uc5; + u8 ued; + u8 umodem; + u8 uir; + u8 reserved; + u8 upfifo; + u8 ucfifo; + u8 usfifo; + u8 utwfifo; + u8 utcfifo; + u8 urwfifo; + u8 urcfifo; + u8 rsvd[28]; +}; + +/* Used on i.MX7ULP */ +#define LPUART_BAUD_BOTHEDGE_MASK (0x20000) +#define LPUART_BAUD_OSR_MASK (0x1F000000) +#define LPUART_BAUD_OSR_SHIFT (24) +#define LPUART_BAUD_OSR(x) ((((uint32_t)(x)) << 24) & 0x1F000000) +#define LPUART_BAUD_SBR_MASK (0x1FFF) +#define LPUART_BAUD_SBR_SHIFT (0U) +#define LPUART_BAUD_SBR(x) (((uint32_t)(x)) & 0x1FFF) +#define LPUART_BAUD_M10_MASK (0x20000000U) +#define LPUART_BAUD_SBNS_MASK (0x2000U) -- cgit v1.3.1 From b60f14574e035eeff91621f91b0781350a3ec332 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 22 Feb 2017 16:21:55 +0800 Subject: mmc: fsl_esdhc: support i.MX7ULP Add compatible property for i.MX7ULP. Add a weak init_usdhc_clk function, i.MX7ULP use this to init the clock. Signed-off-by: Peng Fan Reviewed-by: Jaehoon Chung Reviewed-by : Stefano Babic --- drivers/mmc/fsl_esdhc.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index adeb5df6da9..f3c63585a8e 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -949,6 +949,10 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd) #ifdef CONFIG_DM_MMC #include +__weak void init_clk_usdhc(u32 index) +{ +} + static int fsl_esdhc_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); @@ -1011,6 +1015,9 @@ static int fsl_esdhc_probe(struct udevice *dev) * correctly get the seq as 2 and 3, then let mxc_get_clock * work as expected. */ + + init_clk_usdhc(dev->seq); + priv->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK + dev->seq); if (priv->sdhc_clk <= 0) { dev_err(dev, "Unable to get clk for %s\n", dev->name); @@ -1035,6 +1042,7 @@ static const struct udevice_id fsl_esdhc_ids[] = { { .compatible = "fsl,imx6sl-usdhc", }, { .compatible = "fsl,imx6q-usdhc", }, { .compatible = "fsl,imx7d-usdhc", }, + { .compatible = "fsl,imx7ulp-usdhc", }, { .compatible = "fsl,esdhc", }, { /* sentinel */ } }; -- cgit v1.3.1 From 3a5d63635deb32e68ee15f151de8aeee668f6e2c Mon Sep 17 00:00:00 2001 From: Sébastien Szymanski Date: Tue, 7 Mar 2017 14:33:24 +0100 Subject: dm: imx: serial: add i.MX6UL support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sébastien Szymanski --- drivers/serial/serial_mxc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c index 1cfcbf25b4f..64126e25bf2 100644 --- a/drivers/serial/serial_mxc.c +++ b/drivers/serial/serial_mxc.c @@ -365,6 +365,7 @@ static int mxc_serial_ofdata_to_platdata(struct udevice *dev) } static const struct udevice_id mxc_serial_ids[] = { + { .compatible = "fsl,imx6ul-uart" }, { .compatible = "fsl,imx7d-uart" }, { } }; -- cgit v1.3.1