.. | .. |
---|
77 | 77 | #define OTPC_TIMEOUT_PROG 100000 |
---|
78 | 78 | #define RK3568_NBYTES 2 |
---|
79 | 79 | |
---|
| 80 | +#define RK3588_OTPC_AUTO_CTRL 0x04 |
---|
| 81 | +#define RK3588_OTPC_AUTO_EN 0x08 |
---|
| 82 | +#define RK3588_OTPC_INT_ST 0x84 |
---|
| 83 | +#define RK3588_OTPC_DOUT0 0x20 |
---|
| 84 | +#define RK3588_NO_SECURE_OFFSET 0x300 |
---|
| 85 | +#define RK3588_NBYTES 4 |
---|
| 86 | +#define RK3588_BURST_NUM 1 |
---|
| 87 | +#define RK3588_BURST_SHIFT 8 |
---|
| 88 | +#define RK3588_ADDR_SHIFT 16 |
---|
| 89 | +#define RK3588_AUTO_EN BIT(0) |
---|
| 90 | +#define RK3588_RD_DONE BIT(1) |
---|
| 91 | + |
---|
80 | 92 | #define RV1126_OTP_NVM_CEB 0x00 |
---|
81 | 93 | #define RV1126_OTP_NVM_RSTB 0x04 |
---|
82 | 94 | #define RV1126_OTP_NVM_ST 0x18 |
---|
.. | .. |
---|
144 | 156 | struct rockchip_otp { |
---|
145 | 157 | struct device *dev; |
---|
146 | 158 | void __iomem *base; |
---|
147 | | - struct clk_bulk_data *clks; |
---|
| 159 | + struct clk_bulk_data *clks; |
---|
148 | 160 | int num_clks; |
---|
149 | 161 | struct reset_control *rst; |
---|
150 | 162 | struct nvmem_config *config; |
---|
.. | .. |
---|
302 | 314 | dev_err(otp->dev, "timeout during wait dp2stb\n"); |
---|
303 | 315 | return ret; |
---|
304 | 316 | } |
---|
305 | | - /* fall through */ |
---|
| 317 | + fallthrough; |
---|
306 | 318 | case OTPC_STANDBY: |
---|
307 | 319 | writel(OTPC_ACTIVE, otp->base + OTPC_MODE_CTRL); |
---|
308 | 320 | ret = px30s_otp_wait_status(otp, OTPC_STB2ACT_IRQ_ST); |
---|
.. | .. |
---|
333 | 345 | dev_err(otp->dev, "timeout during wait act2stb\n"); |
---|
334 | 346 | return ret; |
---|
335 | 347 | } |
---|
336 | | - /* fall through */ |
---|
| 348 | + fallthrough; |
---|
337 | 349 | case OTPC_STANDBY: |
---|
338 | 350 | writel(OTPC_DEEP_STANDBY, otp->base + OTPC_MODE_CTRL); |
---|
339 | 351 | ret = px30s_otp_wait_status(otp, OTPC_STB2DP_IRQ_ST); |
---|
.. | .. |
---|
481 | 493 | read_end: |
---|
482 | 494 | writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); |
---|
483 | 495 | disable_clks: |
---|
| 496 | + clk_bulk_disable_unprepare(otp->num_clks, otp->clks); |
---|
| 497 | +out: |
---|
| 498 | + kfree(buf); |
---|
| 499 | + |
---|
| 500 | + return ret; |
---|
| 501 | +} |
---|
| 502 | + |
---|
| 503 | +static int rk3588_otp_wait_status(struct rockchip_otp *otp, u32 flag) |
---|
| 504 | +{ |
---|
| 505 | + u32 status = 0; |
---|
| 506 | + int ret; |
---|
| 507 | + |
---|
| 508 | + ret = readl_poll_timeout_atomic(otp->base + RK3588_OTPC_INT_ST, status, |
---|
| 509 | + (status & flag), 1, OTPC_TIMEOUT); |
---|
| 510 | + if (ret) |
---|
| 511 | + return ret; |
---|
| 512 | + |
---|
| 513 | + /* clean int status */ |
---|
| 514 | + writel(flag, otp->base + RK3588_OTPC_INT_ST); |
---|
| 515 | + |
---|
| 516 | + return 0; |
---|
| 517 | +} |
---|
| 518 | + |
---|
| 519 | +static int rk3588_otp_read(void *context, unsigned int offset, void *val, |
---|
| 520 | + size_t bytes) |
---|
| 521 | +{ |
---|
| 522 | + struct rockchip_otp *otp = context; |
---|
| 523 | + unsigned int addr_start, addr_end, addr_offset, addr_len; |
---|
| 524 | + int ret = 0, i = 0; |
---|
| 525 | + u32 out_value; |
---|
| 526 | + u8 *buf; |
---|
| 527 | + |
---|
| 528 | + if (offset >= otp->data->size) |
---|
| 529 | + return -ENOMEM; |
---|
| 530 | + if (offset + bytes > otp->data->size) |
---|
| 531 | + bytes = otp->data->size - offset; |
---|
| 532 | + |
---|
| 533 | + addr_start = rounddown(offset, RK3588_NBYTES) / RK3588_NBYTES; |
---|
| 534 | + addr_end = roundup(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES; |
---|
| 535 | + addr_offset = offset % RK3588_NBYTES; |
---|
| 536 | + addr_len = addr_end - addr_start; |
---|
| 537 | + addr_start += RK3588_NO_SECURE_OFFSET; |
---|
| 538 | + |
---|
| 539 | + buf = kzalloc(array3_size(addr_len, RK3588_NBYTES, sizeof(*buf)), |
---|
| 540 | + GFP_KERNEL); |
---|
| 541 | + if (!buf) |
---|
| 542 | + return -ENOMEM; |
---|
| 543 | + |
---|
| 544 | + ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks); |
---|
| 545 | + if (ret < 0) { |
---|
| 546 | + dev_err(otp->dev, "failed to prepare/enable clks\n"); |
---|
| 547 | + goto out; |
---|
| 548 | + } |
---|
| 549 | + |
---|
| 550 | + while (addr_len--) { |
---|
| 551 | + writel((addr_start << RK3588_ADDR_SHIFT) | |
---|
| 552 | + (RK3588_BURST_NUM << RK3588_BURST_SHIFT), |
---|
| 553 | + otp->base + RK3588_OTPC_AUTO_CTRL); |
---|
| 554 | + writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN); |
---|
| 555 | + ret = rk3588_otp_wait_status(otp, RK3588_RD_DONE); |
---|
| 556 | + if (ret < 0) { |
---|
| 557 | + dev_err(otp->dev, "timeout during read setup\n"); |
---|
| 558 | + goto read_end; |
---|
| 559 | + } |
---|
| 560 | + |
---|
| 561 | + out_value = readl(otp->base + RK3588_OTPC_DOUT0); |
---|
| 562 | + memcpy(&buf[i], &out_value, RK3588_NBYTES); |
---|
| 563 | + i += RK3588_NBYTES; |
---|
| 564 | + addr_start++; |
---|
| 565 | + } |
---|
| 566 | + |
---|
| 567 | + memcpy(val, buf + addr_offset, bytes); |
---|
| 568 | + |
---|
| 569 | +read_end: |
---|
484 | 570 | clk_bulk_disable_unprepare(otp->num_clks, otp->clks); |
---|
485 | 571 | out: |
---|
486 | 572 | kfree(buf); |
---|
.. | .. |
---|
686 | 772 | .reg_read = rk3568_otp_read, |
---|
687 | 773 | }; |
---|
688 | 774 | |
---|
| 775 | +static const char * const rk3562_otp_clocks[] = { |
---|
| 776 | + "usr", "sbpi", "apb", "arb", "phy", |
---|
| 777 | +}; |
---|
| 778 | + |
---|
| 779 | +static const struct rockchip_data rk3562_data = { |
---|
| 780 | + .size = 0x80, |
---|
| 781 | + .clocks = rk3562_otp_clocks, |
---|
| 782 | + .num_clks = ARRAY_SIZE(rk3562_otp_clocks), |
---|
| 783 | + .reg_read = rk3568_otp_read, |
---|
| 784 | +}; |
---|
| 785 | + |
---|
689 | 786 | static const char * const rk3568_otp_clocks[] = { |
---|
690 | 787 | "usr", "sbpi", "apb", "phy", |
---|
691 | 788 | }; |
---|
.. | .. |
---|
694 | 791 | .size = 0x80, |
---|
695 | 792 | .clocks = rk3568_otp_clocks, |
---|
696 | 793 | .num_clks = ARRAY_SIZE(rk3568_otp_clocks), |
---|
| 794 | + .reg_read = rk3568_otp_read, |
---|
| 795 | +}; |
---|
| 796 | + |
---|
| 797 | +static const char * const rk3588_otp_clocks[] = { |
---|
| 798 | + "otpc", "apb", "arb", "phy", |
---|
| 799 | +}; |
---|
| 800 | + |
---|
| 801 | +static const struct rockchip_data rk3588_data = { |
---|
| 802 | + .size = 0x400, |
---|
| 803 | + .clocks = rk3588_otp_clocks, |
---|
| 804 | + .num_clks = ARRAY_SIZE(rk3588_otp_clocks), |
---|
| 805 | + .reg_read = rk3588_otp_read, |
---|
| 806 | +}; |
---|
| 807 | + |
---|
| 808 | +static const char * const rv1106_otp_clocks[] = { |
---|
| 809 | + "usr", "sbpi", "apb", "phy", "arb", "pmc", |
---|
| 810 | +}; |
---|
| 811 | + |
---|
| 812 | +static const struct rockchip_data rv1106_data = { |
---|
| 813 | + .size = 0x80, |
---|
| 814 | + .clocks = rv1106_otp_clocks, |
---|
| 815 | + .num_clks = ARRAY_SIZE(rv1106_otp_clocks), |
---|
697 | 816 | .reg_read = rk3568_otp_read, |
---|
698 | 817 | }; |
---|
699 | 818 | |
---|
.. | .. |
---|
726 | 845 | .compatible = "rockchip,rk3308-otp", |
---|
727 | 846 | .data = (void *)&px30_data, |
---|
728 | 847 | }, |
---|
| 848 | + { |
---|
| 849 | + .compatible = "rockchip,rk3308bs-otp", |
---|
| 850 | + .data = (void *)&px30s_data, |
---|
| 851 | + }, |
---|
729 | 852 | #endif |
---|
730 | 853 | #ifdef CONFIG_CPU_RK3528 |
---|
731 | 854 | { |
---|
.. | .. |
---|
733 | 856 | .data = (void *)&rk3528_data, |
---|
734 | 857 | }, |
---|
735 | 858 | #endif |
---|
| 859 | +#ifdef CONFIG_CPU_RK3562 |
---|
| 860 | + { |
---|
| 861 | + .compatible = "rockchip,rk3562-otp", |
---|
| 862 | + .data = (void *)&rk3562_data, |
---|
| 863 | + }, |
---|
| 864 | +#endif |
---|
736 | 865 | #ifdef CONFIG_CPU_RK3568 |
---|
737 | 866 | { |
---|
738 | 867 | .compatible = "rockchip,rk3568-otp", |
---|
739 | 868 | .data = (void *)&rk3568_data, |
---|
| 869 | + }, |
---|
| 870 | +#endif |
---|
| 871 | +#ifdef CONFIG_CPU_RK3588 |
---|
| 872 | + { |
---|
| 873 | + .compatible = "rockchip,rk3588-otp", |
---|
| 874 | + .data = (void *)&rk3588_data, |
---|
| 875 | + }, |
---|
| 876 | +#endif |
---|
| 877 | +#ifdef CONFIG_CPU_RV1106 |
---|
| 878 | + { |
---|
| 879 | + .compatible = "rockchip,rv1106-otp", |
---|
| 880 | + .data = (void *)&rv1106_data, |
---|
740 | 881 | }, |
---|
741 | 882 | #endif |
---|
742 | 883 | #ifdef CONFIG_CPU_RV1126 |
---|
.. | .. |
---|
749 | 890 | }; |
---|
750 | 891 | MODULE_DEVICE_TABLE(of, rockchip_otp_match); |
---|
751 | 892 | |
---|
752 | | -static int __init rockchip_otp_probe(struct platform_device *pdev) |
---|
| 893 | +static int rockchip_otp_probe(struct platform_device *pdev) |
---|
753 | 894 | { |
---|
754 | 895 | struct device *dev = &pdev->dev; |
---|
755 | 896 | struct rockchip_otp *otp; |
---|
.. | .. |
---|
762 | 903 | dev_err(dev, "failed to get match data\n"); |
---|
763 | 904 | return -EINVAL; |
---|
764 | 905 | } |
---|
765 | | - if (soc_is_px30s()) |
---|
| 906 | + if (soc_is_px30s() || soc_is_rk3308bs()) |
---|
766 | 907 | data = &px30s_data; |
---|
767 | 908 | |
---|
768 | 909 | otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp), |
---|
.. | .. |
---|
811 | 952 | } |
---|
812 | 953 | |
---|
813 | 954 | static struct platform_driver rockchip_otp_driver = { |
---|
| 955 | + .probe = rockchip_otp_probe, |
---|
814 | 956 | .driver = { |
---|
815 | 957 | .name = "rockchip-otp", |
---|
816 | 958 | .of_match_table = rockchip_otp_match, |
---|
817 | 959 | }, |
---|
818 | 960 | }; |
---|
819 | 961 | |
---|
820 | | -static int __init rockchip_otp_module_init(void) |
---|
| 962 | +static int __init rockchip_otp_init(void) |
---|
821 | 963 | { |
---|
822 | | - return platform_driver_probe(&rockchip_otp_driver, |
---|
823 | | - rockchip_otp_probe); |
---|
| 964 | + int ret; |
---|
| 965 | + |
---|
| 966 | + ret = platform_driver_register(&rockchip_otp_driver); |
---|
| 967 | + if (ret) { |
---|
| 968 | + pr_err("failed to register otp driver\n"); |
---|
| 969 | + return ret; |
---|
| 970 | + } |
---|
| 971 | + |
---|
| 972 | + return 0; |
---|
824 | 973 | } |
---|
825 | 974 | |
---|
826 | | -subsys_initcall(rockchip_otp_module_init); |
---|
| 975 | +static void __exit rockchip_otp_exit(void) |
---|
| 976 | +{ |
---|
| 977 | + return platform_driver_unregister(&rockchip_otp_driver); |
---|
| 978 | +} |
---|
| 979 | + |
---|
| 980 | +subsys_initcall(rockchip_otp_init); |
---|
| 981 | +module_exit(rockchip_otp_exit); |
---|
827 | 982 | |
---|
828 | 983 | MODULE_DESCRIPTION("Rockchip OTP driver"); |
---|
829 | 984 | MODULE_LICENSE("GPL v2"); |
---|