1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 * Core driver for the Ocelot chip family.
5 * The VSC7511, 7512, 7513, and 7514 can be controlled internally via an
6 * on-chip MIPS processor, or externally via SPI, I2C, PCIe. This core driver is
7 * intended to be the bus-agnostic glue between, for example, the SPI bus and
10 * Copyright 2021-2022 Innovative Advantage Inc.
12 * Author: Colin Foster <colin.foster@in-advantage.com>
15 #include <linux/bits.h>
16 #include <linux/device.h>
17 #include <linux/export.h>
18 #include <linux/iopoll.h>
19 #include <linux/ioport.h>
20 #include <linux/kernel.h>
21 #include <linux/mfd/core.h>
22 #include <linux/mfd/ocelot.h>
23 #include <linux/module.h>
24 #include <linux/regmap.h>
25 #include <linux/types.h>
27 #include <soc/mscc/ocelot.h>
31 #define REG_GCB_SOFT_RST 0x0008
33 #define BIT_SOFT_CHIP_RST BIT(0)
35 #define VSC7512_MIIM0_RES_START 0x7107009c
36 #define VSC7512_MIIM1_RES_START 0x710700c0
37 #define VSC7512_MIIM_RES_SIZE 0x024
39 #define VSC7512_PHY_RES_START 0x710700f0
40 #define VSC7512_PHY_RES_SIZE 0x004
42 #define VSC7512_GPIO_RES_START 0x71070034
43 #define VSC7512_GPIO_RES_SIZE 0x06c
45 #define VSC7512_SIO_CTRL_RES_START 0x710700f8
46 #define VSC7512_SIO_CTRL_RES_SIZE 0x100
48 #define VSC7512_GCB_RST_SLEEP_US 100
49 #define VSC7512_GCB_RST_TIMEOUT_US 100000
51 static int ocelot_gcb_chip_rst_status(struct ocelot_ddata *ddata)
55 err = regmap_read(ddata->gcb_regmap, REG_GCB_SOFT_RST, &val);
62 int ocelot_chip_reset(struct device *dev)
64 struct ocelot_ddata *ddata = dev_get_drvdata(dev);
68 * Reset the entire chip here to put it into a completely known state.
69 * Other drivers may want to reset their own subsystems. The register
70 * self-clears, so one write is all that is needed and wait for it to
73 ret = regmap_write(ddata->gcb_regmap, REG_GCB_SOFT_RST, BIT_SOFT_CHIP_RST);
77 return readx_poll_timeout(ocelot_gcb_chip_rst_status, ddata, val, !val,
78 VSC7512_GCB_RST_SLEEP_US, VSC7512_GCB_RST_TIMEOUT_US);
80 EXPORT_SYMBOL_NS(ocelot_chip_reset, MFD_OCELOT);
82 static const struct resource vsc7512_miim0_resources[] = {
83 DEFINE_RES_REG_NAMED(VSC7512_MIIM0_RES_START, VSC7512_MIIM_RES_SIZE, "gcb_miim0"),
84 DEFINE_RES_REG_NAMED(VSC7512_PHY_RES_START, VSC7512_PHY_RES_SIZE, "gcb_phy"),
87 static const struct resource vsc7512_miim1_resources[] = {
88 DEFINE_RES_REG_NAMED(VSC7512_MIIM1_RES_START, VSC7512_MIIM_RES_SIZE, "gcb_miim1"),
91 static const struct resource vsc7512_pinctrl_resources[] = {
92 DEFINE_RES_REG_NAMED(VSC7512_GPIO_RES_START, VSC7512_GPIO_RES_SIZE, "gcb_gpio"),
95 static const struct resource vsc7512_sgpio_resources[] = {
96 DEFINE_RES_REG_NAMED(VSC7512_SIO_CTRL_RES_START, VSC7512_SIO_CTRL_RES_SIZE, "gcb_sio"),
99 static const struct mfd_cell vsc7512_devs[] = {
101 .name = "ocelot-pinctrl",
102 .of_compatible = "mscc,ocelot-pinctrl",
103 .num_resources = ARRAY_SIZE(vsc7512_pinctrl_resources),
104 .resources = vsc7512_pinctrl_resources,
106 .name = "ocelot-sgpio",
107 .of_compatible = "mscc,ocelot-sgpio",
108 .num_resources = ARRAY_SIZE(vsc7512_sgpio_resources),
109 .resources = vsc7512_sgpio_resources,
111 .name = "ocelot-miim0",
112 .of_compatible = "mscc,ocelot-miim",
113 .of_reg = VSC7512_MIIM0_RES_START,
115 .num_resources = ARRAY_SIZE(vsc7512_miim0_resources),
116 .resources = vsc7512_miim0_resources,
118 .name = "ocelot-miim1",
119 .of_compatible = "mscc,ocelot-miim",
120 .of_reg = VSC7512_MIIM1_RES_START,
122 .num_resources = ARRAY_SIZE(vsc7512_miim1_resources),
123 .resources = vsc7512_miim1_resources,
127 static void ocelot_core_try_add_regmap(struct device *dev,
128 const struct resource *res)
130 if (dev_get_regmap(dev, res->name))
133 ocelot_spi_init_regmap(dev, res);
136 static void ocelot_core_try_add_regmaps(struct device *dev,
137 const struct mfd_cell *cell)
141 for (i = 0; i < cell->num_resources; i++)
142 ocelot_core_try_add_regmap(dev, &cell->resources[i]);
145 int ocelot_core_init(struct device *dev)
149 ndevs = ARRAY_SIZE(vsc7512_devs);
151 for (i = 0; i < ndevs; i++)
152 ocelot_core_try_add_regmaps(dev, &vsc7512_devs[i]);
154 return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, vsc7512_devs, ndevs, NULL, 0, NULL);
156 EXPORT_SYMBOL_NS(ocelot_core_init, MFD_OCELOT);
158 MODULE_DESCRIPTION("Externally Controlled Ocelot Chip Driver");
159 MODULE_AUTHOR("Colin Foster <colin.foster@in-advantage.com>");
160 MODULE_LICENSE("GPL");
161 MODULE_IMPORT_NS(MFD_OCELOT_SPI);