diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2018-06-11 22:36:27 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2018-06-11 22:36:27 +0200 |
commit | 63a9b9b25701775833f08984347901f4068b6957 (patch) | |
tree | 6718c2af51c78979dd29231b44cedcba6461b2c2 /arch | |
parent | 2bf93d1edb895287cf275782dee0ec25fce48580 (diff) | |
parent | 636b830eb3af53614cbe59d8b71ba329bd0b5a01 (diff) | |
download | barebox-63a9b9b25701775833f08984347901f4068b6957.tar.gz barebox-63a9b9b25701775833f08984347901f4068b6957.tar.xz |
Merge branch 'for-next/imx-ocotp'
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-imx/Kconfig | 23 | ||||
-rw-r--r-- | arch/arm/mach-imx/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/ocotp.h | 31 | ||||
-rw-r--r-- | arch/arm/mach-imx/ocotp.c | 620 |
4 files changed, 24 insertions, 651 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 85143bd26b..dec5e387e1 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -188,6 +188,7 @@ config ARCH_VF610 select OFTREE select COMMON_CLK select COMMON_CLK_OF_PROVIDER + select NVMEM select IMX_OCOTP # Needed for clock adjustement config IMX_MULTI_BOARDS @@ -734,33 +735,13 @@ config IMX_IIM_FUSE_BLOW enable it: imx_iim0.permanent_write_enable=1 -config IMX_OCOTP - tristate "i.MX6 On Chip OTP controller" - depends on ARCH_IMX6 || ARCH_VF610 - depends on OFDEVICE - help - This adds support for the i.MX6 On-Chip OTP controller. Currently the - only supported functionality is reading the MAC address and assigning - it to an ethernet device. - -config IMX_OCOTP_WRITE - bool - prompt "Enable write support of i.MX6 CPUs OTP fuses" - depends on IMX_OCOTP - help - This adds write support to IMX6 On-Chip OTP registers. Example of set - MAC to 12:34:56:78:9A:BC (2 words with address 0x22 (OCOTP_MAC0) and - address 0x23 (OCOTP_MAC1)). To calculate the file offset multiply - the value of the address by 4. - mw -l -d /dev/imx-ocotp 0x8C 0x00001234 - mw -l -d /dev/imx-ocotp 0x88 0x56789ABC - config HAB bool config HABV4 tristate "HABv4 support" select HAB + select NVMEM select IMX_OCOTP depends on ARCH_IMX6 depends on OFDEVICE diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 43630282a3..442039a276 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_ARCH_VF610) += vf610.o obj-$(CONFIG_ARCH_IMX8MQ) += imx8mq.o obj-$(CONFIG_ARCH_IMX_XLOAD) += xload.o obj-$(CONFIG_IMX_IIM) += iim.o -obj-$(CONFIG_IMX_OCOTP) += ocotp.o obj-$(CONFIG_NAND_IMX) += nand.o lwl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o obj-y += devices.o imx.o diff --git a/arch/arm/mach-imx/include/mach/ocotp.h b/arch/arm/mach-imx/include/mach/ocotp.h index 5474c27ede..76a6da53de 100644 --- a/arch/arm/mach-imx/include/mach/ocotp.h +++ b/arch/arm/mach-imx/include/mach/ocotp.h @@ -1,17 +1,30 @@ #ifndef __MACH_IMX_OCOTP_H #define __MACH_IMX_OCOTP_H -#define OCOTP_WORD_MASK_WIDTH 8 -#define OCOTP_WORD_MASK_SHIFT 0 -#define OCOTP_WORD(n) ((((n) - 0x400) >> 4) & ((1 << OCOTP_WORD_MASK_WIDTH) - 1)) +#include <linux/bitfield.h> -#define OCOTP_BIT_MASK_WIDTH 5 -#define OCOTP_BIT_MASK_SHIFT (OCOTP_WORD_MASK_SHIFT + OCOTP_WORD_MASK_WIDTH) -#define OCOTP_BIT(n) (((n) & ((1 << OCOTP_BIT_MASK_WIDTH) - 1)) << OCOTP_BIT_MASK_SHIFT) +#define OCOTP_SHADOW_OFFSET 0x400 +#define OCOTP_SHADOW_SPACING 0x10 + +/* + * Trivial shadow register offset -> ocotp register index. + * + * NOTE: Doesn't handle special mapping quirks. See + * imx6q_addr_to_offset and vf610_addr_to_offset for more details. Use + * with care + */ +#define OCOTP_OFFSET_TO_INDEX(o) \ + (((o) - OCOTP_SHADOW_OFFSET) / OCOTP_SHADOW_SPACING) + +#define OCOTP_WORD_MASK GENMASK( 7, 0) +#define OCOTP_BIT_MASK GENMASK(12, 8) +#define OCOTP_WIDTH_MASK GENMASK(17, 13) + +#define OCOTP_WORD(n) FIELD_PREP(OCOTP_WORD_MASK, \ + OCOTP_OFFSET_TO_INDEX(n)) +#define OCOTP_BIT(n) FIELD_PREP(OCOTP_BIT_MASK, n) +#define OCOTP_WIDTH(n) FIELD_PREP(OCOTP_WIDTH_MASK, (n) - 1) -#define OCOTP_WIDTH_MASK_WIDTH 5 -#define OCOTP_WIDTH_MASK_SHIFT (OCOTP_BIT_MASK_SHIFT + OCOTP_BIT_MASK_WIDTH) -#define OCOTP_WIDTH(n) ((((n) - 1) & ((1 << OCOTP_WIDTH_MASK_WIDTH) - 1)) << OCOTP_WIDTH_MASK_SHIFT) int imx_ocotp_read_field(uint32_t field, unsigned *value); int imx_ocotp_write_field(uint32_t field, unsigned value); diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c deleted file mode 100644 index 99b365aad8..0000000000 --- a/arch/arm/mach-imx/ocotp.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - * ocotp.c - i.MX6 ocotp fusebox driver - * - * Provide an interface for programming and sensing the information that are - * stored in on-chip fuse elements. This functionality is part of the IC - * Identification Module (IIM), which is present on some i.MX CPUs. - * - * Copyright (c) 2010 Baruch Siach <baruch@tkos.co.il>, - * Orex Computed Radiography - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include <common.h> -#include <driver.h> -#include <malloc.h> -#include <xfuncs.h> -#include <errno.h> -#include <init.h> -#include <net.h> -#include <io.h> -#include <of.h> -#include <clock.h> -#include <regmap.h> -#include <linux/clk.h> -#include <mach/ocotp.h> - -/* - * a single MAC address reference has the form - * <&phandle regoffset> - */ -#define MAC_ADDRESS_PROPLEN (2 * sizeof(__be32)) - -/* OCOTP Registers offsets */ -#define OCOTP_CTRL 0x00 -#define OCOTP_CTRL_SET 0x04 -#define OCOTP_CTRL_CLR 0x08 -#define OCOTP_TIMING 0x10 -#define OCOTP_DATA 0x20 -#define OCOTP_READ_CTRL 0x30 -#define OCOTP_READ_FUSE_DATA 0x40 - -/* OCOTP Registers bits and masks */ -#define OCOTP_CTRL_WR_UNLOCK 16 -#define OCOTP_CTRL_WR_UNLOCK_KEY 0x3E77 -#define OCOTP_CTRL_WR_UNLOCK_MASK 0xFFFF0000 -#define OCOTP_CTRL_ADDR 0 -#define OCOTP_CTRL_ADDR_MASK 0x0000007F -#define OCOTP_CTRL_BUSY (1 << 8) -#define OCOTP_CTRL_ERROR (1 << 9) -#define OCOTP_CTRL_RELOAD_SHADOWS (1 << 10) - -#define OCOTP_TIMING_STROBE_READ 16 -#define OCOTP_TIMING_STROBE_READ_MASK 0x003F0000 -#define OCOTP_TIMING_RELAX 12 -#define OCOTP_TIMING_RELAX_MASK 0x0000F000 -#define OCOTP_TIMING_STROBE_PROG 0 -#define OCOTP_TIMING_STROBE_PROG_MASK 0x00000FFF - -#define OCOTP_READ_CTRL_READ_FUSE 0x00000001 - -#define BF(value, field) (((value) << field) & field##_MASK) - -/* Other definitions */ -#define IMX6_OTP_DATA_ERROR_VAL 0xBADABADA -#define DEF_RELAX 20 -#define MAC_OFFSET_0 (0x22 * 4) -#define MAC_OFFSET_1 (0x24 * 4) -#define MAX_MAC_OFFSETS 2 -#define MAC_BYTES 8 - -struct imx_ocotp_data { - int num_regs; - u32 (*addr_to_offset)(u32 addr); - u8 mac_offsets[MAX_MAC_OFFSETS]; - u8 mac_offsets_num; -}; - -struct ocotp_priv_ethaddr { - char value[MAC_BYTES]; - struct regmap *map; - u8 offset; -}; - -struct ocotp_priv { - struct regmap *map; - void __iomem *base; - struct clk *clk; - struct device_d dev; - int permanent_write_enable; - int sense_enable; - struct ocotp_priv_ethaddr ethaddr[MAX_MAC_OFFSETS]; - struct regmap_config map_config; - const struct imx_ocotp_data *data; - int mac_offset_idx; -}; - -static struct ocotp_priv *imx_ocotp; - -static int imx6_ocotp_set_timing(struct ocotp_priv *priv) -{ - u32 clk_rate; - u32 relax, strobe_read, strobe_prog; - u32 timing; - - clk_rate = clk_get_rate(priv->clk); - - relax = clk_rate / (1000000000 / DEF_RELAX) - 1; - strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1; - strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1; - - timing = BF(relax, OCOTP_TIMING_RELAX); - timing |= BF(strobe_read, OCOTP_TIMING_STROBE_READ); - timing |= BF(strobe_prog, OCOTP_TIMING_STROBE_PROG); - - writel(timing, priv->base + OCOTP_TIMING); - - return 0; -} - -static int imx6_ocotp_wait_busy(struct ocotp_priv *priv, u32 flags) -{ - uint64_t start = get_time_ns(); - - while (readl(priv->base + OCOTP_CTRL) & (OCOTP_CTRL_BUSY | flags)) - if (is_timeout(start, MSECOND)) - return -ETIMEDOUT; - - return 0; -} - -static int imx6_ocotp_prepare(struct ocotp_priv *priv) -{ - int ret; - - ret = imx6_ocotp_set_timing(priv); - if (ret) - return ret; - - ret = imx6_ocotp_wait_busy(priv, 0); - if (ret) - return ret; - - return 0; -} - -static int fuse_read_addr(struct ocotp_priv *priv, u32 addr, u32 *pdata) -{ - u32 ctrl_reg; - int ret; - - writel(OCOTP_CTRL_ERROR, priv->base + OCOTP_CTRL_CLR); - - ctrl_reg = readl(priv->base + OCOTP_CTRL); - ctrl_reg &= ~OCOTP_CTRL_ADDR_MASK; - ctrl_reg &= ~OCOTP_CTRL_WR_UNLOCK_MASK; - ctrl_reg |= BF(addr, OCOTP_CTRL_ADDR); - writel(ctrl_reg, priv->base + OCOTP_CTRL); - - writel(OCOTP_READ_CTRL_READ_FUSE, priv->base + OCOTP_READ_CTRL); - ret = imx6_ocotp_wait_busy(priv, 0); - if (ret) - return ret; - - if (readl(priv->base + OCOTP_CTRL) & OCOTP_CTRL_ERROR) - *pdata = 0xbadabada; - else - *pdata = readl(priv->base + OCOTP_READ_FUSE_DATA); - - return 0; -} - -int imx6_ocotp_read_one_u32(struct ocotp_priv *priv, u32 index, u32 *pdata) -{ - int ret; - - ret = imx6_ocotp_prepare(priv); - if (ret) { - dev_err(&priv->dev, "failed to prepare read fuse 0x%08x\n", - index); - return ret; - } - - ret = fuse_read_addr(priv, index, pdata); - if (ret) { - dev_err(&priv->dev, "failed to read fuse 0x%08x\n", index); - return ret; - } - - return 0; -} - -static int imx_ocotp_reg_read(void *ctx, unsigned int reg, unsigned int *val) -{ - struct ocotp_priv *priv = ctx; - u32 index; - int ret; - - index = reg >> 2; - - if (priv->sense_enable) { - ret = imx6_ocotp_read_one_u32(priv, index, val); - if (ret) - return ret; - } else { - *(u32 *)val = readl(priv->base + - priv->data->addr_to_offset(index)); - } - - return 0; -} - -static int fuse_blow_addr(struct ocotp_priv *priv, u32 addr, u32 value) -{ - u32 ctrl_reg; - int ret; - - writel(OCOTP_CTRL_ERROR, priv->base + OCOTP_CTRL_CLR); - - /* Control register */ - ctrl_reg = readl(priv->base + OCOTP_CTRL); - ctrl_reg &= ~OCOTP_CTRL_ADDR_MASK; - ctrl_reg |= BF(addr, OCOTP_CTRL_ADDR); - ctrl_reg |= BF(OCOTP_CTRL_WR_UNLOCK_KEY, OCOTP_CTRL_WR_UNLOCK); - writel(ctrl_reg, priv->base + OCOTP_CTRL); - - writel(value, priv->base + OCOTP_DATA); - ret = imx6_ocotp_wait_busy(priv, 0); - if (ret) - return ret; - - /* Write postamble */ - udelay(2000); - return 0; -} - -static int imx6_ocotp_reload_shadow(struct ocotp_priv *priv) -{ - dev_info(&priv->dev, "reloading shadow registers...\n"); - writel(OCOTP_CTRL_RELOAD_SHADOWS, priv->base + OCOTP_CTRL_SET); - udelay(1); - - return imx6_ocotp_wait_busy(priv, OCOTP_CTRL_RELOAD_SHADOWS); -} - -int imx6_ocotp_blow_one_u32(struct ocotp_priv *priv, u32 index, u32 data, - u32 *pfused_value) -{ - int ret; - - ret = imx6_ocotp_prepare(priv); - if (ret) { - dev_err(&priv->dev, "prepare to write failed\n"); - return ret; - } - - ret = fuse_blow_addr(priv, index, data); - if (ret) { - dev_err(&priv->dev, "fuse blow failed\n"); - return ret; - } - - if (readl(priv->base + OCOTP_CTRL) & OCOTP_CTRL_ERROR) { - dev_err(&priv->dev, "bad write status\n"); - return -EFAULT; - } - - ret = imx6_ocotp_read_one_u32(priv, index, pfused_value); - - return ret; -} - -static int imx_ocotp_reg_write(void *ctx, unsigned int reg, unsigned int val) -{ - struct ocotp_priv *priv = ctx; - int index; - u32 pfuse; - int ret; - - index = reg >> 2; - - if (priv->permanent_write_enable) { - ret = imx6_ocotp_blow_one_u32(priv, index, val, &pfuse); - if (ret < 0) - return ret; - } else { - writel(val, priv->base + - priv->data->addr_to_offset(index)); - } - - if (priv->permanent_write_enable) - imx6_ocotp_reload_shadow(priv); - - return 0; -} - -static void imx_ocotp_field_decode(uint32_t field, unsigned *word, - unsigned *bit, unsigned *mask) -{ - unsigned width; - - *word = ((field >> OCOTP_WORD_MASK_SHIFT) & ((1 << OCOTP_WORD_MASK_WIDTH) - 1)) * 4; - *bit = (field >> OCOTP_BIT_MASK_SHIFT) & ((1 << OCOTP_BIT_MASK_WIDTH) - 1); - width = ((field >> OCOTP_WIDTH_MASK_SHIFT) & ((1 << OCOTP_WIDTH_MASK_WIDTH) - 1)) + 1; - *mask = (1 << width) - 1; -} - -int imx_ocotp_read_field(uint32_t field, unsigned *value) -{ - unsigned word, bit, mask, val; - int ret; - - imx_ocotp_field_decode(field, &word, &bit, &mask); - - ret = imx_ocotp_reg_read(imx_ocotp, word, &val); - if (ret) - return ret; - - val >>= bit; - val &= mask; - - dev_dbg(&imx_ocotp->dev, "%s: word: 0x%x bit: %d mask: 0x%x val: 0x%x\n", - __func__, word, bit, mask, val); - - *value = val; - - return 0; -} - -int imx_ocotp_write_field(uint32_t field, unsigned value) -{ - unsigned word, bit, mask; - int ret; - - imx_ocotp_field_decode(field, &word, &bit, &mask); - - value &= mask; - value <<= bit; - - ret = imx_ocotp_reg_write(imx_ocotp, word, value); - if (ret) - return ret; - - dev_dbg(&imx_ocotp->dev, "%s: word: 0x%x bit: %d mask: 0x%x val: 0x%x\n", - __func__, word, bit, mask, value); - - return 0; -} - -int imx_ocotp_permanent_write(int enable) -{ - imx_ocotp->permanent_write_enable = enable; - - return 0; -} - -bool imx_ocotp_sense_enable(bool enable) -{ - const bool old_value = imx_ocotp->sense_enable; - imx_ocotp->sense_enable = enable; - return old_value; -} - -static uint32_t inc_offset(uint32_t offset) -{ - if ((offset & 0x3) == 0x3) - return offset + 0xd; - else - return offset + 1; -} - -static void imx_ocotp_init_dt(struct device_d *dev, void __iomem *base) -{ - char mac[6]; - const __be32 *prop; - struct device_node *node = dev->device_node; - int len; - - if (!node) - return; - - prop = of_get_property(node, "barebox,provide-mac-address", &len); - if (!prop) - return; - - while (len >= MAC_ADDRESS_PROPLEN) { - struct device_node *rnode; - uint32_t phandle, offset; - - phandle = be32_to_cpup(prop++); - - rnode = of_find_node_by_phandle(phandle); - offset = be32_to_cpup(prop++); - - mac[5] = readb(base + offset); - offset = inc_offset(offset); - mac[4] = readb(base + offset); - offset = inc_offset(offset); - mac[3] = readb(base + offset); - offset = inc_offset(offset); - mac[2] = readb(base + offset); - offset = inc_offset(offset); - mac[1] = readb(base + offset); - offset = inc_offset(offset); - mac[0] = readb(base + offset); - - of_eth_register_ethaddr(rnode, mac); - - len -= MAC_ADDRESS_PROPLEN; - } -} - -static void memreverse(void *dest, const void *src, size_t n) -{ - char *destp = dest; - const char *srcp = src + n - 1; - - while(n--) - *destp++ = *srcp--; -} - -static int imx_ocotp_get_mac(struct param_d *param, void *priv) -{ - char buf[MAC_BYTES]; - int ret; - struct ocotp_priv_ethaddr *ethaddr = priv; - - ret = regmap_bulk_read(ethaddr->map, ethaddr->offset, - buf, MAC_BYTES); - if (ret < 0) - return ret; - - memreverse(ethaddr->value, buf, 6); - return 0; -} - -static int imx_ocotp_set_mac(struct param_d *param, void *priv) -{ - char buf[MAC_BYTES]; - struct ocotp_priv_ethaddr *ethaddr = priv; - - memreverse(buf, ethaddr->value, 6); - - return regmap_bulk_write(ethaddr->map, ethaddr->offset, - buf, MAC_BYTES); -} - -static struct regmap_bus imx_ocotp_regmap_bus = { - .reg_write = imx_ocotp_reg_write, - .reg_read = imx_ocotp_reg_read, -}; - -static int imx_ocotp_probe(struct device_d *dev) -{ - struct resource *iores; - void __iomem *base; - struct ocotp_priv *priv; - int ret = 0; - const struct imx_ocotp_data *data; - - ret = dev_get_drvdata(dev, (const void **)&data); - if (ret) - return ret; - - iores = dev_request_mem_resource(dev, 0); - if (IS_ERR(iores)) - return PTR_ERR(iores); - base = IOMEM(iores->start); - - imx_ocotp_init_dt(dev, base); - - priv = xzalloc(sizeof(*priv)); - - priv->data = data; - priv->base = base; - priv->clk = clk_get(dev, NULL); - if (IS_ERR(priv->clk)) - return PTR_ERR(priv->clk); - - strcpy(priv->dev.name, "ocotp"); - priv->dev.parent = dev; - register_device(&priv->dev); - - priv->map_config.reg_bits = 32; - priv->map_config.val_bits = 32; - priv->map_config.reg_stride = 4; - priv->map_config.max_register = data->num_regs - 1; - - priv->map = regmap_init(dev, &imx_ocotp_regmap_bus, priv, &priv->map_config); - if (IS_ERR(priv->map)) - return PTR_ERR(priv->map); - - ret = regmap_register_cdev(priv->map, "imx-ocotp"); - if (ret) - return ret; - - imx_ocotp = priv; - - if (IS_ENABLED(CONFIG_IMX_OCOTP_WRITE)) { - dev_add_param_bool(&(priv->dev), "permanent_write_enable", - NULL, NULL, &priv->permanent_write_enable, NULL); - } - - if (IS_ENABLED(CONFIG_NET)) { - int i; - struct ocotp_priv_ethaddr *ethaddr; - - for (i = 0; i < priv->data->mac_offsets_num; i++) { - ethaddr = &priv->ethaddr[i]; - ethaddr->map = priv->map; - ethaddr->offset = priv->data->mac_offsets[i]; - - dev_add_param_mac(&priv->dev, xasprintf("mac_addr%d", i), - imx_ocotp_set_mac, imx_ocotp_get_mac, - ethaddr->value, ethaddr); - } - - /* - * Alias to mac_addr0 for backwards compatibility - */ - ethaddr = &priv->ethaddr[0]; - dev_add_param_mac(&priv->dev, "mac_addr", - imx_ocotp_set_mac, imx_ocotp_get_mac, - ethaddr->value, ethaddr); - } - - dev_add_param_bool(&(priv->dev), "sense_enable", NULL, NULL, &priv->sense_enable, priv); - - return 0; -} - -static u32 imx6sl_addr_to_offset(u32 addr) -{ - return 0x400 + addr * 0x10; -} - -static u32 imx6q_addr_to_offset(u32 addr) -{ - u32 addendum = 0; - - if (addr > 0x2F) { - /* - * If we are reading past Bank 5, take into account a - * 0x100 bytes wide gap between Bank 5 and Bank 6 - */ - addendum += 0x100; - } - - - return imx6sl_addr_to_offset(addr) + addendum; -} - -static u32 vf610_addr_to_offset(u32 addr) -{ - if (addr == 0x04) - return 0x450; - else - return imx6q_addr_to_offset(addr); -} - -static struct imx_ocotp_data imx6q_ocotp_data = { - .num_regs = 512, - .addr_to_offset = imx6q_addr_to_offset, - .mac_offsets_num = 1, - .mac_offsets = { MAC_OFFSET_0 }, -}; - -static struct imx_ocotp_data imx6sl_ocotp_data = { - .num_regs = 256, - .addr_to_offset = imx6sl_addr_to_offset, - .mac_offsets_num = 1, - .mac_offsets = { MAC_OFFSET_0 }, -}; - -static struct imx_ocotp_data vf610_ocotp_data = { - .num_regs = 512, - .addr_to_offset = vf610_addr_to_offset, - .mac_offsets_num = 2, - .mac_offsets = { MAC_OFFSET_0, MAC_OFFSET_1 }, -}; - -static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = { - { - .compatible = "fsl,imx6q-ocotp", - .data = &imx6q_ocotp_data, - }, { - .compatible = "fsl,imx6sx-ocotp", - .data = &imx6q_ocotp_data, - }, { - .compatible = "fsl,imx6sl-ocotp", - .data = &imx6sl_ocotp_data, - }, { - .compatible = "fsl,imx6ul-ocotp", - .data = &imx6q_ocotp_data, - }, { - .compatible = "fsl,vf610-ocotp", - .data = &vf610_ocotp_data, - }, { - /* sentinel */ - } -}; - -static struct driver_d imx_ocotp_driver = { - .name = "imx_ocotp", - .probe = imx_ocotp_probe, - .of_compatible = DRV_OF_COMPAT(imx_ocotp_dt_ids), -}; - -static int imx_ocotp_init(void) -{ - platform_driver_register(&imx_ocotp_driver); - - return 0; -} -postcore_initcall(imx_ocotp_init); |