Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * I2C driver for Renesas Synchronization Management Unit (SMU) devices.
0004  *
0005  * Copyright (C) 2021 Integrated Device Technology, Inc., a Renesas Company.
0006  */
0007 
0008 #include <linux/i2c.h>
0009 #include <linux/init.h>
0010 #include <linux/kernel.h>
0011 #include <linux/mfd/core.h>
0012 #include <linux/mfd/rsmu.h>
0013 #include <linux/module.h>
0014 #include <linux/of.h>
0015 #include <linux/regmap.h>
0016 #include <linux/slab.h>
0017 
0018 #include "rsmu.h"
0019 
0020 /*
0021  * 16-bit register address: the lower 8 bits of the register address come
0022  * from the offset addr byte and the upper 8 bits come from the page register.
0023  */
0024 #define RSMU_CM_PAGE_ADDR       0xFD
0025 #define RSMU_CM_PAGE_WINDOW     256
0026 
0027 /*
0028  * 15-bit register address: the lower 7 bits of the register address come
0029  * from the offset addr byte and the upper 8 bits come from the page register.
0030  */
0031 #define RSMU_SABRE_PAGE_ADDR        0x7F
0032 #define RSMU_SABRE_PAGE_WINDOW      128
0033 
0034 static const struct regmap_range_cfg rsmu_cm_range_cfg[] = {
0035     {
0036         .range_min = 0,
0037         .range_max = 0xD000,
0038         .selector_reg = RSMU_CM_PAGE_ADDR,
0039         .selector_mask = 0xFF,
0040         .selector_shift = 0,
0041         .window_start = 0,
0042         .window_len = RSMU_CM_PAGE_WINDOW,
0043     }
0044 };
0045 
0046 static const struct regmap_range_cfg rsmu_sabre_range_cfg[] = {
0047     {
0048         .range_min = 0,
0049         .range_max = 0x400,
0050         .selector_reg = RSMU_SABRE_PAGE_ADDR,
0051         .selector_mask = 0xFF,
0052         .selector_shift = 0,
0053         .window_start = 0,
0054         .window_len = RSMU_SABRE_PAGE_WINDOW,
0055     }
0056 };
0057 
0058 static bool rsmu_cm_volatile_reg(struct device *dev, unsigned int reg)
0059 {
0060     switch (reg) {
0061     case RSMU_CM_PAGE_ADDR:
0062         return false;
0063     default:
0064         return true;
0065     }
0066 }
0067 
0068 static bool rsmu_sabre_volatile_reg(struct device *dev, unsigned int reg)
0069 {
0070     switch (reg) {
0071     case RSMU_SABRE_PAGE_ADDR:
0072         return false;
0073     default:
0074         return true;
0075     }
0076 }
0077 
0078 static const struct regmap_config rsmu_cm_regmap_config = {
0079     .reg_bits = 8,
0080     .val_bits = 8,
0081     .max_register = 0xD000,
0082     .ranges = rsmu_cm_range_cfg,
0083     .num_ranges = ARRAY_SIZE(rsmu_cm_range_cfg),
0084     .volatile_reg = rsmu_cm_volatile_reg,
0085     .cache_type = REGCACHE_RBTREE,
0086     .can_multi_write = true,
0087 };
0088 
0089 static const struct regmap_config rsmu_sabre_regmap_config = {
0090     .reg_bits = 8,
0091     .val_bits = 8,
0092     .max_register = 0x400,
0093     .ranges = rsmu_sabre_range_cfg,
0094     .num_ranges = ARRAY_SIZE(rsmu_sabre_range_cfg),
0095     .volatile_reg = rsmu_sabre_volatile_reg,
0096     .cache_type = REGCACHE_RBTREE,
0097     .can_multi_write = true,
0098 };
0099 
0100 static const struct regmap_config rsmu_sl_regmap_config = {
0101     .reg_bits = 16,
0102     .val_bits = 8,
0103     .reg_format_endian = REGMAP_ENDIAN_BIG,
0104     .max_register = 0x339,
0105     .cache_type = REGCACHE_NONE,
0106     .can_multi_write = true,
0107 };
0108 
0109 static int rsmu_i2c_probe(struct i2c_client *client,
0110               const struct i2c_device_id *id)
0111 {
0112     const struct regmap_config *cfg;
0113     struct rsmu_ddata *rsmu;
0114     int ret;
0115 
0116     rsmu = devm_kzalloc(&client->dev, sizeof(*rsmu), GFP_KERNEL);
0117     if (!rsmu)
0118         return -ENOMEM;
0119 
0120     i2c_set_clientdata(client, rsmu);
0121 
0122     rsmu->dev = &client->dev;
0123     rsmu->type = (enum rsmu_type)id->driver_data;
0124 
0125     switch (rsmu->type) {
0126     case RSMU_CM:
0127         cfg = &rsmu_cm_regmap_config;
0128         break;
0129     case RSMU_SABRE:
0130         cfg = &rsmu_sabre_regmap_config;
0131         break;
0132     case RSMU_SL:
0133         cfg = &rsmu_sl_regmap_config;
0134         break;
0135     default:
0136         dev_err(rsmu->dev, "Unsupported RSMU device type: %d\n", rsmu->type);
0137         return -ENODEV;
0138     }
0139     rsmu->regmap = devm_regmap_init_i2c(client, cfg);
0140     if (IS_ERR(rsmu->regmap)) {
0141         ret = PTR_ERR(rsmu->regmap);
0142         dev_err(rsmu->dev, "Failed to allocate register map: %d\n", ret);
0143         return ret;
0144     }
0145 
0146     return rsmu_core_init(rsmu);
0147 }
0148 
0149 static int rsmu_i2c_remove(struct i2c_client *client)
0150 {
0151     struct rsmu_ddata *rsmu = i2c_get_clientdata(client);
0152 
0153     rsmu_core_exit(rsmu);
0154 
0155     return 0;
0156 }
0157 
0158 static const struct i2c_device_id rsmu_i2c_id[] = {
0159     { "8a34000",  RSMU_CM },
0160     { "8a34001",  RSMU_CM },
0161     { "82p33810", RSMU_SABRE },
0162     { "82p33811", RSMU_SABRE },
0163     { "8v19n850", RSMU_SL },
0164     { "8v19n851", RSMU_SL },
0165     {}
0166 };
0167 MODULE_DEVICE_TABLE(i2c, rsmu_i2c_id);
0168 
0169 static const struct of_device_id rsmu_i2c_of_match[] = {
0170     { .compatible = "idt,8a34000",  .data = (void *)RSMU_CM },
0171     { .compatible = "idt,8a34001",  .data = (void *)RSMU_CM },
0172     { .compatible = "idt,82p33810", .data = (void *)RSMU_SABRE },
0173     { .compatible = "idt,82p33811", .data = (void *)RSMU_SABRE },
0174     { .compatible = "idt,8v19n850", .data = (void *)RSMU_SL },
0175     { .compatible = "idt,8v19n851", .data = (void *)RSMU_SL },
0176     {}
0177 };
0178 MODULE_DEVICE_TABLE(of, rsmu_i2c_of_match);
0179 
0180 static struct i2c_driver rsmu_i2c_driver = {
0181     .driver = {
0182         .name = "rsmu-i2c",
0183         .of_match_table = of_match_ptr(rsmu_i2c_of_match),
0184     },
0185     .probe = rsmu_i2c_probe,
0186     .remove = rsmu_i2c_remove,
0187     .id_table = rsmu_i2c_id,
0188 };
0189 
0190 static int __init rsmu_i2c_init(void)
0191 {
0192     return i2c_add_driver(&rsmu_i2c_driver);
0193 }
0194 subsys_initcall(rsmu_i2c_init);
0195 
0196 static void __exit rsmu_i2c_exit(void)
0197 {
0198     i2c_del_driver(&rsmu_i2c_driver);
0199 }
0200 module_exit(rsmu_i2c_exit);
0201 
0202 MODULE_DESCRIPTION("Renesas SMU I2C driver");
0203 MODULE_LICENSE("GPL");