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
71 * @name: name if available71 * @name: name if available
72 * @revision: interconnect target module revision72 * @revision: interconnect target module revision
73 * @needs_resume: runtime resume needed on resume from suspend73 * @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
74 */77 */
75struct sysc {78struct sysc {
76 struct device *dev;79 struct device *dev;
@@ -94,6 +97,9 @@ struct sysc { · 17 unmodified lines
94 unsigned int child_needs_resume:1;97 unsigned int child_needs_resume:1;
95 unsigned int disable_on_idle:1;98 unsigned int disable_on_idle:1;
96 struct delayed_work idle_work;99 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);
97};103};
98 104
99static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,105static 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
760 ddata->offsets[SYSC_SYSCONFIG],766 ddata->offsets[SYSC_SYSCONFIG],
761 ddata->offsets[SYSC_SYSSTATUS]);767 ddata->offsets[SYSC_SYSSTATUS]);
762 768
769 if (size < SZ_1K)
770 size = SZ_1K;
771
763 if ((size + sizeof(u32)) > ddata->module_size)772 if ((size + sizeof(u32)) > ddata->module_size)
764 return -EINVAL;773 size = ddata->module_size;
765 }774 }
766 775
767 ddata->module_va = devm_ioremap(ddata->dev,776 ddata->module_va = devm_ioremap(ddata->dev,
@@ -1234,6 +1243,22 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 466 unmodified lines
1234 SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT |1243 SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT |
1235 SYSC_QUIRK_SWSUP_SIDLE),1244 SYSC_QUIRK_SWSUP_SIDLE),
1236 1245
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
1237#ifdef DEBUG1262#ifdef DEBUG
1238 SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0),1263 SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0),
1239 SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0),1264 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
1247 SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),1272 SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),
1248 SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),1273 SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),
1249 SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0),1274 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),
1252 SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0),1275 SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0),
1253 SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0),1276 SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0),
1254 SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, 0),
1255 SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0),1277 SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0),
1256 SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0),1278 SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0),
1257 SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0),1279 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
1287 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -1, 0x50700101, 0xffffffff, 0),1309 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -1, 0x50700101, 0xffffffff, 0),
1288 SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,1310 SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
1289 0xffffffff, 0),1311 0xffffffff, 0),
1290 SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, 0),
1291 SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0),1312 SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0),
1292#endif1313#endif
1293};1314};
@@ -1360,6 +1381,94 @@ static void sysc_init_revision_quirks(struct sysc *ddata) · 66 unmodified lines
1360 }1381 }
1361}1382}
1362 1383
1384/* 1-wire needs module's internal clocks enabled for reset */
1385static 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 */
1396static 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
1416static void sysc_clk_enable_quirk_i2c(struct sysc *ddata)
1417{
1418 sysc_clk_quirk_i2c(ddata, true);
1419}
1420
1421static 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 */
1427static 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
1450static 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
1363static int sysc_clockdomain_init(struct sysc *ddata)1472static int sysc_clockdomain_init(struct sysc *ddata)
1364{1473{
1365 struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);1474 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
1468 else1577 else
1469 syss_done = ddata->cfg.syss_mask;1578 syss_done = ddata->cfg.syss_mask;
1470 1579
1580 if (ddata->clk_disable_quirk)
1581 ddata->clk_disable_quirk(ddata);
1582
1471 sysc_val = sysc_read_sysconfig(ddata);1583 sysc_val = sysc_read_sysconfig(ddata);
1472 sysc_val |= sysc_mask;1584 sysc_val |= sysc_mask;
1473 sysc_write(ddata, sysc_offset, sysc_val);1585 sysc_write(ddata, sysc_offset, sysc_val);
1474 1586
1587 if (ddata->clk_enable_quirk)
1588 ddata->clk_enable_quirk(ddata);
1589
1475 /* Poll on reset status */1590 /* Poll on reset status */
1476 if (syss_offset >= 0) {1591 if (syss_offset >= 0) {
1477 error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval,1592 error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval,
@@ -1485,6 +1600,9 @@ static int sysc_reset(struct sysc *ddata) · 7 unmodified lines
1485 100, MAX_MODULE_SOFTRESET_WAIT);1600 100, MAX_MODULE_SOFTRESET_WAIT);
1486 }1601 }
1487 1602
1603 if (ddata->reset_done_quirk)
1604 ddata->reset_done_quirk(ddata);
1605
1488 return error;1606 return error;
1489}1607}
1490 1608
@@ -1531,6 +1649,7 @@ static int sysc_init_module(struct sysc *ddata) · 40 unmodified lines
1531 1649
1532 ddata->revision = sysc_read_revision(ddata);1650 ddata->revision = sysc_read_revision(ddata);
1533 sysc_init_revision_quirks(ddata);1651 sysc_init_revision_quirks(ddata);
1652 sysc_init_module_quirks(ddata);
1534 1653
1535 if (ddata->legacy_mode) {1654 if (ddata->legacy_mode) {
1536 error = sysc_legacy_init(ddata);1655 error = sysc_legacy_init(ddata);
include/linux/platform_data/ti-sysc.h+3−0
@@ -47,6 +47,9 @@ struct sysc_regbits { · 46 unmodified lines
47 s8 emufree_shift;47 s8 emufree_shift;
48};48};
49 49
50#define SYSC_MODULE_QUIRK_HDQ1W BIT(17)
51#define SYSC_MODULE_QUIRK_I2C BIT(16)
52#define SYSC_MODULE_QUIRK_WDT BIT(15)
50#define SYSS_QUIRK_RESETDONE_INVERTED BIT(14)53#define SYSS_QUIRK_RESETDONE_INVERTED BIT(14)
51#define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13)54#define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13)
52#define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12)55#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