diff options
| -rw-r--r-- | drivers/bus/ti-sysc.c | 129 | ||||
| -rw-r--r-- | include/linux/platform_data/ti-sysc.h | 3 |
2 files changed, 127 insertions, 5 deletions
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index a366ae548ec9..e6deabd8305d 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c | |||
| @@ -71,6 +71,9 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = { | |||
| 71 | * @name: name if available | 71 | * @name: name if available |
| 72 | * @revision: interconnect target module revision | 72 | * @revision: interconnect target module revision |
| 73 | * @needs_resume: runtime resume needed on resume from suspend | 73 | * @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 | */ |
| 75 | struct sysc { | 78 | struct sysc { |
| 76 | struct device *dev; | 79 | struct device *dev; |
| @@ -94,6 +97,9 @@ struct sysc { | |||
| 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 | ||
| 99 | static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np, | 105 | static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np, |
| @@ -760,8 +766,11 @@ static int sysc_ioremap(struct sysc *ddata) | |||
| 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[] = { | |||
| 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 DEBUG | 1262 | #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[] = { | |||
| 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[] = { | |||
| 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 | #endif | 1313 | #endif |
| 1293 | }; | 1314 | }; |
| @@ -1360,6 +1381,94 @@ static void sysc_init_revision_quirks(struct sysc *ddata) | |||
| 1360 | } | 1381 | } |
| 1361 | } | 1382 | } |
| 1362 | 1383 | ||
| 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 | |||
| 1363 | static int sysc_clockdomain_init(struct sysc *ddata) | 1472 | static 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) | |||
| 1468 | else | 1577 | 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) | |||
| 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) | |||
| 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); |
diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 8822e99ff813..0c587d4fc718 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h | |||
| @@ -47,6 +47,9 @@ struct sysc_regbits { | |||
| 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) |
