root/drivers/soc/actions/owl-sps.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. owl_sps_set_power
  2. owl_sps_power_on
  3. owl_sps_power_off
  4. owl_sps_init_domain
  5. owl_sps_probe
  6. owl_sps_init

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Actions Semi Owl Smart Power System (SPS)
   4  *
   5  * Copyright 2012 Actions Semi Inc.
   6  * Author: Actions Semi, Inc.
   7  *
   8  * Copyright (c) 2017 Andreas Färber
   9  */
  10 
  11 #include <linux/of_address.h>
  12 #include <linux/of_platform.h>
  13 #include <linux/pm_domain.h>
  14 #include <linux/soc/actions/owl-sps.h>
  15 #include <dt-bindings/power/owl-s500-powergate.h>
  16 #include <dt-bindings/power/owl-s700-powergate.h>
  17 #include <dt-bindings/power/owl-s900-powergate.h>
  18 
  19 struct owl_sps_domain_info {
  20         const char *name;
  21         int pwr_bit;
  22         int ack_bit;
  23         unsigned int genpd_flags;
  24 };
  25 
  26 struct owl_sps_info {
  27         unsigned num_domains;
  28         const struct owl_sps_domain_info *domains;
  29 };
  30 
  31 struct owl_sps {
  32         struct device *dev;
  33         const struct owl_sps_info *info;
  34         void __iomem *base;
  35         struct genpd_onecell_data genpd_data;
  36         struct generic_pm_domain *domains[];
  37 };
  38 
  39 #define to_owl_pd(gpd) container_of(gpd, struct owl_sps_domain, genpd)
  40 
  41 struct owl_sps_domain {
  42         struct generic_pm_domain genpd;
  43         const struct owl_sps_domain_info *info;
  44         struct owl_sps *sps;
  45 };
  46 
  47 static int owl_sps_set_power(struct owl_sps_domain *pd, bool enable)
  48 {
  49         u32 pwr_mask, ack_mask;
  50 
  51         ack_mask = BIT(pd->info->ack_bit);
  52         pwr_mask = BIT(pd->info->pwr_bit);
  53 
  54         return owl_sps_set_pg(pd->sps->base, pwr_mask, ack_mask, enable);
  55 }
  56 
  57 static int owl_sps_power_on(struct generic_pm_domain *domain)
  58 {
  59         struct owl_sps_domain *pd = to_owl_pd(domain);
  60 
  61         dev_dbg(pd->sps->dev, "%s power on", pd->info->name);
  62 
  63         return owl_sps_set_power(pd, true);
  64 }
  65 
  66 static int owl_sps_power_off(struct generic_pm_domain *domain)
  67 {
  68         struct owl_sps_domain *pd = to_owl_pd(domain);
  69 
  70         dev_dbg(pd->sps->dev, "%s power off", pd->info->name);
  71 
  72         return owl_sps_set_power(pd, false);
  73 }
  74 
  75 static int owl_sps_init_domain(struct owl_sps *sps, int index)
  76 {
  77         struct owl_sps_domain *pd;
  78 
  79         pd = devm_kzalloc(sps->dev, sizeof(*pd), GFP_KERNEL);
  80         if (!pd)
  81                 return -ENOMEM;
  82 
  83         pd->info = &sps->info->domains[index];
  84         pd->sps = sps;
  85 
  86         pd->genpd.name = pd->info->name;
  87         pd->genpd.power_on = owl_sps_power_on;
  88         pd->genpd.power_off = owl_sps_power_off;
  89         pd->genpd.flags = pd->info->genpd_flags;
  90         pm_genpd_init(&pd->genpd, NULL, false);
  91 
  92         sps->genpd_data.domains[index] = &pd->genpd;
  93 
  94         return 0;
  95 }
  96 
  97 static int owl_sps_probe(struct platform_device *pdev)
  98 {
  99         const struct of_device_id *match;
 100         const struct owl_sps_info *sps_info;
 101         struct owl_sps *sps;
 102         int i, ret;
 103 
 104         if (!pdev->dev.of_node) {
 105                 dev_err(&pdev->dev, "no device node\n");
 106                 return -ENODEV;
 107         }
 108 
 109         match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
 110         if (!match || !match->data) {
 111                 dev_err(&pdev->dev, "unknown compatible or missing data\n");
 112                 return -EINVAL;
 113         }
 114 
 115         sps_info = match->data;
 116 
 117         sps = devm_kzalloc(&pdev->dev,
 118                            struct_size(sps, domains, sps_info->num_domains),
 119                            GFP_KERNEL);
 120         if (!sps)
 121                 return -ENOMEM;
 122 
 123         sps->base = of_io_request_and_map(pdev->dev.of_node, 0, "owl-sps");
 124         if (IS_ERR(sps->base)) {
 125                 dev_err(&pdev->dev, "failed to map sps registers\n");
 126                 return PTR_ERR(sps->base);
 127         }
 128 
 129         sps->dev = &pdev->dev;
 130         sps->info = sps_info;
 131         sps->genpd_data.domains = sps->domains;
 132         sps->genpd_data.num_domains = sps_info->num_domains;
 133 
 134         for (i = 0; i < sps_info->num_domains; i++) {
 135                 ret = owl_sps_init_domain(sps, i);
 136                 if (ret)
 137                         return ret;
 138         }
 139 
 140         ret = of_genpd_add_provider_onecell(pdev->dev.of_node, &sps->genpd_data);
 141         if (ret) {
 142                 dev_err(&pdev->dev, "failed to add provider (%d)", ret);
 143                 return ret;
 144         }
 145 
 146         return 0;
 147 }
 148 
 149 static const struct owl_sps_domain_info s500_sps_domains[] = {
 150         [S500_PD_VDE] = {
 151                 .name = "VDE",
 152                 .pwr_bit = 0,
 153                 .ack_bit = 16,
 154         },
 155         [S500_PD_VCE_SI] = {
 156                 .name = "VCE_SI",
 157                 .pwr_bit = 1,
 158                 .ack_bit = 17,
 159         },
 160         [S500_PD_USB2_1] = {
 161                 .name = "USB2_1",
 162                 .pwr_bit = 2,
 163                 .ack_bit = 18,
 164         },
 165         [S500_PD_CPU2] = {
 166                 .name = "CPU2",
 167                 .pwr_bit = 5,
 168                 .ack_bit = 21,
 169                 .genpd_flags = GENPD_FLAG_ALWAYS_ON,
 170         },
 171         [S500_PD_CPU3] = {
 172                 .name = "CPU3",
 173                 .pwr_bit = 6,
 174                 .ack_bit = 22,
 175                 .genpd_flags = GENPD_FLAG_ALWAYS_ON,
 176         },
 177         [S500_PD_DMA] = {
 178                 .name = "DMA",
 179                 .pwr_bit = 8,
 180                 .ack_bit = 12,
 181         },
 182         [S500_PD_DS] = {
 183                 .name = "DS",
 184                 .pwr_bit = 9,
 185                 .ack_bit = 13,
 186         },
 187         [S500_PD_USB3] = {
 188                 .name = "USB3",
 189                 .pwr_bit = 10,
 190                 .ack_bit = 14,
 191         },
 192         [S500_PD_USB2_0] = {
 193                 .name = "USB2_0",
 194                 .pwr_bit = 11,
 195                 .ack_bit = 15,
 196         },
 197 };
 198 
 199 static const struct owl_sps_info s500_sps_info = {
 200         .num_domains = ARRAY_SIZE(s500_sps_domains),
 201         .domains = s500_sps_domains,
 202 };
 203 
 204 static const struct owl_sps_domain_info s700_sps_domains[] = {
 205         [S700_PD_VDE] = {
 206                 .name = "VDE",
 207                 .pwr_bit = 0,
 208         },
 209         [S700_PD_VCE_SI] = {
 210                 .name = "VCE_SI",
 211                 .pwr_bit = 1,
 212         },
 213         [S700_PD_USB2_1] = {
 214                 .name = "USB2_1",
 215                 .pwr_bit = 2,
 216         },
 217         [S700_PD_HDE] = {
 218                 .name = "HDE",
 219                 .pwr_bit = 7,
 220         },
 221         [S700_PD_DMA] = {
 222                 .name = "DMA",
 223                 .pwr_bit = 8,
 224         },
 225         [S700_PD_DS] = {
 226                 .name = "DS",
 227                 .pwr_bit = 9,
 228         },
 229         [S700_PD_USB3] = {
 230                 .name = "USB3",
 231                 .pwr_bit = 10,
 232         },
 233         [S700_PD_USB2_0] = {
 234                 .name = "USB2_0",
 235                 .pwr_bit = 11,
 236         },
 237 };
 238 
 239 static const struct owl_sps_info s700_sps_info = {
 240         .num_domains = ARRAY_SIZE(s700_sps_domains),
 241         .domains = s700_sps_domains,
 242 };
 243 
 244 static const struct owl_sps_domain_info s900_sps_domains[] = {
 245         [S900_PD_GPU_B] = {
 246                 .name = "GPU_B",
 247                 .pwr_bit = 3,
 248         },
 249         [S900_PD_VCE] = {
 250                 .name = "VCE",
 251                 .pwr_bit = 4,
 252         },
 253         [S900_PD_SENSOR] = {
 254                 .name = "SENSOR",
 255                 .pwr_bit = 5,
 256         },
 257         [S900_PD_VDE] = {
 258                 .name = "VDE",
 259                 .pwr_bit = 6,
 260         },
 261         [S900_PD_HDE] = {
 262                 .name = "HDE",
 263                 .pwr_bit = 7,
 264         },
 265         [S900_PD_USB3] = {
 266                 .name = "USB3",
 267                 .pwr_bit = 8,
 268         },
 269         [S900_PD_DDR0] = {
 270                 .name = "DDR0",
 271                 .pwr_bit = 9,
 272         },
 273         [S900_PD_DDR1] = {
 274                 .name = "DDR1",
 275                 .pwr_bit = 10,
 276         },
 277         [S900_PD_DE] = {
 278                 .name = "DE",
 279                 .pwr_bit = 13,
 280         },
 281         [S900_PD_NAND] = {
 282                 .name = "NAND",
 283                 .pwr_bit = 14,
 284         },
 285         [S900_PD_USB2_H0] = {
 286                 .name = "USB2_H0",
 287                 .pwr_bit = 15,
 288         },
 289         [S900_PD_USB2_H1] = {
 290                 .name = "USB2_H1",
 291                 .pwr_bit = 16,
 292         },
 293 };
 294 
 295 static const struct owl_sps_info s900_sps_info = {
 296         .num_domains = ARRAY_SIZE(s900_sps_domains),
 297         .domains = s900_sps_domains,
 298 };
 299 
 300 static const struct of_device_id owl_sps_of_matches[] = {
 301         { .compatible = "actions,s500-sps", .data = &s500_sps_info },
 302         { .compatible = "actions,s700-sps", .data = &s700_sps_info },
 303         { .compatible = "actions,s900-sps", .data = &s900_sps_info },
 304         { }
 305 };
 306 
 307 static struct platform_driver owl_sps_platform_driver = {
 308         .probe = owl_sps_probe,
 309         .driver = {
 310                 .name = "owl-sps",
 311                 .of_match_table = owl_sps_of_matches,
 312                 .suppress_bind_attrs = true,
 313         },
 314 };
 315 
 316 static int __init owl_sps_init(void)
 317 {
 318         return platform_driver_register(&owl_sps_platform_driver);
 319 }
 320 postcore_initcall(owl_sps_init);

/* [<][>][^][v][top][bottom][index][help] */