History

bus: ti-sysc: Add support for module specific reset quirks

Some older interconnect target modules need module internal clock toggling quirks to reset properly. We've been doing this in the platform code earlier, but need to be able to it directly in the ti-sysc driver when we no longer rely on on the platform code. Let's add reset handling for 1-wire, i2c and watchdog. Later on we can add more modules like msdi and dss as they get tested. For dra7 pcie, we should be able to just use the rstctrl reset driver when available.

Tony Lindgren committed 7 years ago

Commit 4e23be41 parent b6a53c42 files · +127 −5Browse files

Unified · Split

2 files
  1. drivers/bus/ti-sysc.c +124 −5
  2. include/linux/platform_data/ti-sysc.h +3 −0
drivers/bus/ti-sysc.c+124−5
@@ -71,6 +71,9 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = { · 70 unmodified lines
7171 * @name: name if available
7272 * @revision: interconnect target module revision
7373 * @needs_resume: runtime resume needed on resume from suspend
74+ * @clk_enable_quirk: module specific clock enable quirk
75+ * @clk_disable_quirk: module specific clock disable quirk
76+ * @reset_done_quirk: module specific reset done quirk
7477 */
7578 struct sysc {
7679 struct device *dev;
@@ -94,6 +97,9 @@ struct sysc { · 17 unmodified lines
9497 unsigned int child_needs_resume:1;
9598 unsigned int disable_on_idle:1;
9699 struct delayed_work idle_work;
100+ void (*clk_enable_quirk)(struct sysc *sysc);
101+ void (*clk_disable_quirk)(struct sysc *sysc);
102+ void (*reset_done_quirk)(struct sysc *sysc);
97103 };
98104
99105 static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
@@ -760,8 +766,11 @@ static int sysc_ioremap(struct sysc *ddata) · 660 unmodified lines
760766 ddata->offsets[SYSC_SYSCONFIG],
761767 ddata->offsets[SYSC_SYSSTATUS]);
762768
769+ if (size < SZ_1K)
770+ size = SZ_1K;
771+
763772 if ((size + sizeof(u32)) > ddata->module_size)
764− return -EINVAL;
773+ size = ddata->module_size;
765774 }
766775
767776 ddata->module_va = devm_ioremap(ddata->dev,
@@ -1234,6 +1243,22 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 466 unmodified lines
12341243 SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT |
12351244 SYSC_QUIRK_SWSUP_SIDLE),
12361245
1246+ /* Quirks that need to be set based on detected module */
1247+ SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff,
1248+ SYSC_MODULE_QUIRK_HDQ1W),
1249+ SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff,
1250+ SYSC_MODULE_QUIRK_HDQ1W),
1251+ SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000036, 0x000000ff,
1252+ SYSC_MODULE_QUIRK_I2C),
1253+ SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x0000003c, 0x000000ff,
1254+ SYSC_MODULE_QUIRK_I2C),
1255+ SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000040, 0x000000ff,
1256+ SYSC_MODULE_QUIRK_I2C),
1257+ SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0,
1258+ SYSC_MODULE_QUIRK_I2C),
1259+ SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0,
1260+ SYSC_MODULE_QUIRK_WDT),
1261+
12371262 #ifdef DEBUG
12381263 SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0),
12391264 SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0),
@@ -1247,11 +1272,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 7 unmodified lines
12471272 SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),
12481273 SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),
12491274 SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0),
1250− SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, 0),
1251− SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, 0),
12521275 SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0),
12531276 SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0),
1254− SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, 0),
12551277 SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0),
12561278 SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0),
12571279 SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0),
@@ -1287,7 +1309,6 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 29 unmodified lines
12871309 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -1, 0x50700101, 0xffffffff, 0),
12881310 SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
12891311 0xffffffff, 0),
1290− SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, 0),
12911312 SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0),
12921313 #endif
12931314 };
@@ -1360,6 +1381,94 @@ static void sysc_init_revision_quirks(struct sysc *ddata) · 66 unmodified lines
13601381 }
13611382 }
13621383
1384+/* 1-wire needs module's internal clocks enabled for reset */
1385+static void sysc_clk_enable_quirk_hdq1w(struct sysc *ddata)
1386+{
1387+ int offset = 0x0c; /* HDQ_CTRL_STATUS */
1388+ u16 val;
1389+
1390+ val = sysc_read(ddata, offset);
1391+ val |= BIT(5);
1392+ sysc_write(ddata, offset, val);
1393+}
1394+
1395+/* I2C needs extra enable bit toggling for reset */
1396+static void sysc_clk_quirk_i2c(struct sysc *ddata, bool enable)
1397+{
1398+ int offset;
1399+ u16 val;
1400+
1401+ /* I2C_CON, omap2/3 is different from omap4 and later */
1402+ if ((ddata->revision & 0xffffff00) == 0x001f0000)
1403+ offset = 0x24;
1404+ else
1405+ offset = 0xa4;
1406+
1407+ /* I2C_EN */
1408+ val = sysc_read(ddata, offset);
1409+ if (enable)
1410+ val |= BIT(15);
1411+ else
1412+ val &= ~BIT(15);
1413+ sysc_write(ddata, offset, val);
1414+}
1415+
1416+static void sysc_clk_enable_quirk_i2c(struct sysc *ddata)
1417+{
1418+ sysc_clk_quirk_i2c(ddata, true);
1419+}
1420+
1421+static void sysc_clk_disable_quirk_i2c(struct sysc *ddata)
1422+{
1423+ sysc_clk_quirk_i2c(ddata, false);
1424+}
1425+
1426+/* Watchdog timer needs a disable sequence after reset */
1427+static void sysc_reset_done_quirk_wdt(struct sysc *ddata)
1428+{
1429+ int wps, spr, error;
1430+ u32 val;
1431+
1432+ wps = 0x34;
1433+ spr = 0x48;
1434+
1435+ sysc_write(ddata, spr, 0xaaaa);
1436+ error = readl_poll_timeout(ddata->module_va + wps, val,
1437+ !(val & 0x10), 100,
1438+ MAX_MODULE_SOFTRESET_WAIT);
1439+ if (error)
1440+ dev_warn(ddata->dev, "wdt disable spr failed\n");
1441+
1442+ sysc_write(ddata, wps, 0x5555);
1443+ error = readl_poll_timeout(ddata->module_va + wps, val,
1444+ !(val & 0x10), 100,
1445+ MAX_MODULE_SOFTRESET_WAIT);
1446+ if (error)
1447+ dev_warn(ddata->dev, "wdt disable wps failed\n");
1448+}
1449+
1450+static void sysc_init_module_quirks(struct sysc *ddata)
1451+{
1452+ if (ddata->legacy_mode || !ddata->name)
1453+ return;
1454+
1455+ if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_HDQ1W) {
1456+ ddata->clk_enable_quirk = sysc_clk_enable_quirk_hdq1w;
1457+
1458+ return;
1459+ }
1460+
1461+ if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_I2C) {
1462+ ddata->clk_enable_quirk = sysc_clk_enable_quirk_i2c;
1463+ ddata->clk_disable_quirk = sysc_clk_disable_quirk_i2c;
1464+
1465+ return;
1466+ }
1467+
1468+ if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_WDT)
1469+ ddata->reset_done_quirk = sysc_reset_done_quirk_wdt;
1470+}
1471+
13631472 static int sysc_clockdomain_init(struct sysc *ddata)
13641473 {
13651474 struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
@@ -1468,10 +1577,16 @@ static int sysc_reset(struct sysc *ddata) · 102 unmodified lines
14681577 else
14691578 syss_done = ddata->cfg.syss_mask;
14701579
1580+ if (ddata->clk_disable_quirk)
1581+ ddata->clk_disable_quirk(ddata);
1582+
14711583 sysc_val = sysc_read_sysconfig(ddata);
14721584 sysc_val |= sysc_mask;
14731585 sysc_write(ddata, sysc_offset, sysc_val);
14741586
1587+ if (ddata->clk_enable_quirk)
1588+ ddata->clk_enable_quirk(ddata);
1589+
14751590 /* Poll on reset status */
14761591 if (syss_offset >= 0) {
14771592 error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval,
@@ -1485,6 +1600,9 @@ static int sysc_reset(struct sysc *ddata) · 7 unmodified lines
14851600 100, MAX_MODULE_SOFTRESET_WAIT);
14861601 }
14871602
1603+ if (ddata->reset_done_quirk)
1604+ ddata->reset_done_quirk(ddata);
1605+
14881606 return error;
14891607 }
14901608
@@ -1531,6 +1649,7 @@ static int sysc_init_module(struct sysc *ddata) · 40 unmodified lines
15311649
15321650 ddata->revision = sysc_read_revision(ddata);
15331651 sysc_init_revision_quirks(ddata);
1652+ sysc_init_module_quirks(ddata);
15341653
15351654 if (ddata->legacy_mode) {
15361655 error = sysc_legacy_init(ddata);
include/linux/platform_data/ti-sysc.h+3−0
@@ -47,6 +47,9 @@ struct sysc_regbits { · 46 unmodified lines
4747 s8 emufree_shift;
4848 };
4949
50+#define SYSC_MODULE_QUIRK_HDQ1W BIT(17)
51+#define SYSC_MODULE_QUIRK_I2C BIT(16)
52+#define SYSC_MODULE_QUIRK_WDT BIT(15)
5053 #define SYSS_QUIRK_RESETDONE_INVERTED BIT(14)
5154 #define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13)
5255 #define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t