Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Actions Semi Owl Smart Power System (SPS)
0004  *
0005  * Copyright 2012 Actions Semi Inc.
0006  * Author: Actions Semi, Inc.
0007  *
0008  * Copyright (c) 2017 Andreas Färber
0009  */
0010 
0011 #include <linux/of_address.h>
0012 #include <linux/of_platform.h>
0013 #include <linux/pm_domain.h>
0014 #include <linux/soc/actions/owl-sps.h>
0015 #include <dt-bindings/power/owl-s500-powergate.h>
0016 #include <dt-bindings/power/owl-s700-powergate.h>
0017 #include <dt-bindings/power/owl-s900-powergate.h>
0018 
0019 struct owl_sps_domain_info {
0020     const char *name;
0021     int pwr_bit;
0022     int ack_bit;
0023     unsigned int genpd_flags;
0024 };
0025 
0026 struct owl_sps_info {
0027     unsigned num_domains;
0028     const struct owl_sps_domain_info *domains;
0029 };
0030 
0031 struct owl_sps {
0032     struct device *dev;
0033     const struct owl_sps_info *info;
0034     void __iomem *base;
0035     struct genpd_onecell_data genpd_data;
0036     struct generic_pm_domain *domains[];
0037 };
0038 
0039 #define to_owl_pd(gpd) container_of(gpd, struct owl_sps_domain, genpd)
0040 
0041 struct owl_sps_domain {
0042     struct generic_pm_domain genpd;
0043     const struct owl_sps_domain_info *info;
0044     struct owl_sps *sps;
0045 };
0046 
0047 static int owl_sps_set_power(struct owl_sps_domain *pd, bool enable)
0048 {
0049     u32 pwr_mask, ack_mask;
0050 
0051     ack_mask = BIT(pd->info->ack_bit);
0052     pwr_mask = BIT(pd->info->pwr_bit);
0053 
0054     return owl_sps_set_pg(pd->sps->base, pwr_mask, ack_mask, enable);
0055 }
0056 
0057 static int owl_sps_power_on(struct generic_pm_domain *domain)
0058 {
0059     struct owl_sps_domain *pd = to_owl_pd(domain);
0060 
0061     dev_dbg(pd->sps->dev, "%s power on", pd->info->name);
0062 
0063     return owl_sps_set_power(pd, true);
0064 }
0065 
0066 static int owl_sps_power_off(struct generic_pm_domain *domain)
0067 {
0068     struct owl_sps_domain *pd = to_owl_pd(domain);
0069 
0070     dev_dbg(pd->sps->dev, "%s power off", pd->info->name);
0071 
0072     return owl_sps_set_power(pd, false);
0073 }
0074 
0075 static int owl_sps_init_domain(struct owl_sps *sps, int index)
0076 {
0077     struct owl_sps_domain *pd;
0078 
0079     pd = devm_kzalloc(sps->dev, sizeof(*pd), GFP_KERNEL);
0080     if (!pd)
0081         return -ENOMEM;
0082 
0083     pd->info = &sps->info->domains[index];
0084     pd->sps = sps;
0085 
0086     pd->genpd.name = pd->info->name;
0087     pd->genpd.power_on = owl_sps_power_on;
0088     pd->genpd.power_off = owl_sps_power_off;
0089     pd->genpd.flags = pd->info->genpd_flags;
0090     pm_genpd_init(&pd->genpd, NULL, false);
0091 
0092     sps->genpd_data.domains[index] = &pd->genpd;
0093 
0094     return 0;
0095 }
0096 
0097 static int owl_sps_probe(struct platform_device *pdev)
0098 {
0099     const struct of_device_id *match;
0100     const struct owl_sps_info *sps_info;
0101     struct owl_sps *sps;
0102     int i, ret;
0103 
0104     if (!pdev->dev.of_node) {
0105         dev_err(&pdev->dev, "no device node\n");
0106         return -ENODEV;
0107     }
0108 
0109     match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
0110     if (!match || !match->data) {
0111         dev_err(&pdev->dev, "unknown compatible or missing data\n");
0112         return -EINVAL;
0113     }
0114 
0115     sps_info = match->data;
0116 
0117     sps = devm_kzalloc(&pdev->dev,
0118                struct_size(sps, domains, sps_info->num_domains),
0119                GFP_KERNEL);
0120     if (!sps)
0121         return -ENOMEM;
0122 
0123     sps->base = of_io_request_and_map(pdev->dev.of_node, 0, "owl-sps");
0124     if (IS_ERR(sps->base)) {
0125         dev_err(&pdev->dev, "failed to map sps registers\n");
0126         return PTR_ERR(sps->base);
0127     }
0128 
0129     sps->dev = &pdev->dev;
0130     sps->info = sps_info;
0131     sps->genpd_data.domains = sps->domains;
0132     sps->genpd_data.num_domains = sps_info->num_domains;
0133 
0134     for (i = 0; i < sps_info->num_domains; i++) {
0135         ret = owl_sps_init_domain(sps, i);
0136         if (ret)
0137             return ret;
0138     }
0139 
0140     ret = of_genpd_add_provider_onecell(pdev->dev.of_node, &sps->genpd_data);
0141     if (ret) {
0142         dev_err(&pdev->dev, "failed to add provider (%d)", ret);
0143         return ret;
0144     }
0145 
0146     return 0;
0147 }
0148 
0149 static const struct owl_sps_domain_info s500_sps_domains[] = {
0150     [S500_PD_VDE] = {
0151         .name = "VDE",
0152         .pwr_bit = 0,
0153         .ack_bit = 16,
0154     },
0155     [S500_PD_VCE_SI] = {
0156         .name = "VCE_SI",
0157         .pwr_bit = 1,
0158         .ack_bit = 17,
0159     },
0160     [S500_PD_USB2_1] = {
0161         .name = "USB2_1",
0162         .pwr_bit = 2,
0163         .ack_bit = 18,
0164     },
0165     [S500_PD_CPU2] = {
0166         .name = "CPU2",
0167         .pwr_bit = 5,
0168         .ack_bit = 21,
0169         .genpd_flags = GENPD_FLAG_ALWAYS_ON,
0170     },
0171     [S500_PD_CPU3] = {
0172         .name = "CPU3",
0173         .pwr_bit = 6,
0174         .ack_bit = 22,
0175         .genpd_flags = GENPD_FLAG_ALWAYS_ON,
0176     },
0177     [S500_PD_DMA] = {
0178         .name = "DMA",
0179         .pwr_bit = 8,
0180         .ack_bit = 12,
0181     },
0182     [S500_PD_DS] = {
0183         .name = "DS",
0184         .pwr_bit = 9,
0185         .ack_bit = 13,
0186     },
0187     [S500_PD_USB3] = {
0188         .name = "USB3",
0189         .pwr_bit = 10,
0190         .ack_bit = 14,
0191     },
0192     [S500_PD_USB2_0] = {
0193         .name = "USB2_0",
0194         .pwr_bit = 11,
0195         .ack_bit = 15,
0196     },
0197 };
0198 
0199 static const struct owl_sps_info s500_sps_info = {
0200     .num_domains = ARRAY_SIZE(s500_sps_domains),
0201     .domains = s500_sps_domains,
0202 };
0203 
0204 static const struct owl_sps_domain_info s700_sps_domains[] = {
0205     [S700_PD_VDE] = {
0206         .name = "VDE",
0207         .pwr_bit = 0,
0208     },
0209     [S700_PD_VCE_SI] = {
0210         .name = "VCE_SI",
0211         .pwr_bit = 1,
0212     },
0213     [S700_PD_USB2_1] = {
0214         .name = "USB2_1",
0215         .pwr_bit = 2,
0216     },
0217     [S700_PD_HDE] = {
0218         .name = "HDE",
0219         .pwr_bit = 7,
0220     },
0221     [S700_PD_DMA] = {
0222         .name = "DMA",
0223         .pwr_bit = 8,
0224     },
0225     [S700_PD_DS] = {
0226         .name = "DS",
0227         .pwr_bit = 9,
0228     },
0229     [S700_PD_USB3] = {
0230         .name = "USB3",
0231         .pwr_bit = 10,
0232     },
0233     [S700_PD_USB2_0] = {
0234         .name = "USB2_0",
0235         .pwr_bit = 11,
0236     },
0237 };
0238 
0239 static const struct owl_sps_info s700_sps_info = {
0240     .num_domains = ARRAY_SIZE(s700_sps_domains),
0241     .domains = s700_sps_domains,
0242 };
0243 
0244 static const struct owl_sps_domain_info s900_sps_domains[] = {
0245     [S900_PD_GPU_B] = {
0246         .name = "GPU_B",
0247         .pwr_bit = 3,
0248     },
0249     [S900_PD_VCE] = {
0250         .name = "VCE",
0251         .pwr_bit = 4,
0252     },
0253     [S900_PD_SENSOR] = {
0254         .name = "SENSOR",
0255         .pwr_bit = 5,
0256     },
0257     [S900_PD_VDE] = {
0258         .name = "VDE",
0259         .pwr_bit = 6,
0260     },
0261     [S900_PD_HDE] = {
0262         .name = "HDE",
0263         .pwr_bit = 7,
0264     },
0265     [S900_PD_USB3] = {
0266         .name = "USB3",
0267         .pwr_bit = 8,
0268     },
0269     [S900_PD_DDR0] = {
0270         .name = "DDR0",
0271         .pwr_bit = 9,
0272     },
0273     [S900_PD_DDR1] = {
0274         .name = "DDR1",
0275         .pwr_bit = 10,
0276     },
0277     [S900_PD_DE] = {
0278         .name = "DE",
0279         .pwr_bit = 13,
0280     },
0281     [S900_PD_NAND] = {
0282         .name = "NAND",
0283         .pwr_bit = 14,
0284     },
0285     [S900_PD_USB2_H0] = {
0286         .name = "USB2_H0",
0287         .pwr_bit = 15,
0288     },
0289     [S900_PD_USB2_H1] = {
0290         .name = "USB2_H1",
0291         .pwr_bit = 16,
0292     },
0293 };
0294 
0295 static const struct owl_sps_info s900_sps_info = {
0296     .num_domains = ARRAY_SIZE(s900_sps_domains),
0297     .domains = s900_sps_domains,
0298 };
0299 
0300 static const struct of_device_id owl_sps_of_matches[] = {
0301     { .compatible = "actions,s500-sps", .data = &s500_sps_info },
0302     { .compatible = "actions,s700-sps", .data = &s700_sps_info },
0303     { .compatible = "actions,s900-sps", .data = &s900_sps_info },
0304     { }
0305 };
0306 
0307 static struct platform_driver owl_sps_platform_driver = {
0308     .probe = owl_sps_probe,
0309     .driver = {
0310         .name = "owl-sps",
0311         .of_match_table = owl_sps_of_matches,
0312         .suppress_bind_attrs = true,
0313     },
0314 };
0315 
0316 static int __init owl_sps_init(void)
0317 {
0318     return platform_driver_register(&owl_sps_platform_driver);
0319 }
0320 postcore_initcall(owl_sps_init);