Commit 7f9c1362 authored by Venkata Narendra Kumar Gutta's avatar Venkata Narendra Kumar Gutta Committed by Andy Gross

soc: qcom: Add broadcast base for Last Level Cache Controller (LLCC)

Currently, broadcast base is set to end of the LLCC banks, which may
not be correct always. As the number of banks may vary for each chipset
and the broadcast base could be at a different address as well. This info
depends on the chipset, so get the broadcast base info from the device
tree (DT). Add broadcast base in LLCC driver and use this for broadcast
writes.
Signed-off-by: default avatarVenkata Narendra Kumar Gutta <vnkgutta@codeaurora.org>
Reviewed-by: default avatarEvan Green <evgreen@chromium.org>
Signed-off-by: default avatarAndy Gross <andy.gross@linaro.org>
parent 5b394b2d
...@@ -106,22 +106,24 @@ static int llcc_update_act_ctrl(u32 sid, ...@@ -106,22 +106,24 @@ static int llcc_update_act_ctrl(u32 sid,
u32 slice_status; u32 slice_status;
int ret; int ret;
act_ctrl_reg = drv_data->bcast_off + LLCC_TRP_ACT_CTRLn(sid); act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid);
status_reg = drv_data->bcast_off + LLCC_TRP_STATUSn(sid); status_reg = LLCC_TRP_STATUSn(sid);
/* Set the ACTIVE trigger */ /* Set the ACTIVE trigger */
act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG; act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG;
ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val); ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg,
act_ctrl_reg_val);
if (ret) if (ret)
return ret; return ret;
/* Clear the ACTIVE trigger */ /* Clear the ACTIVE trigger */
act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG; act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG;
ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val); ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg,
act_ctrl_reg_val);
if (ret) if (ret)
return ret; return ret;
ret = regmap_read_poll_timeout(drv_data->regmap, status_reg, ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg,
slice_status, !(slice_status & status), slice_status, !(slice_status & status),
0, LLCC_STATUS_READ_DELAY); 0, LLCC_STATUS_READ_DELAY);
return ret; return ret;
...@@ -226,16 +228,13 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev) ...@@ -226,16 +228,13 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev)
int ret; int ret;
const struct llcc_slice_config *llcc_table; const struct llcc_slice_config *llcc_table;
struct llcc_slice_desc desc; struct llcc_slice_desc desc;
u32 bcast_off = drv_data->bcast_off;
sz = drv_data->cfg_size; sz = drv_data->cfg_size;
llcc_table = drv_data->cfg; llcc_table = drv_data->cfg;
for (i = 0; i < sz; i++) { for (i = 0; i < sz; i++) {
attr1_cfg = bcast_off + attr1_cfg = LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id); attr0_cfg = LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
attr0_cfg = bcast_off +
LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
attr1_val = llcc_table[i].cache_mode; attr1_val = llcc_table[i].cache_mode;
attr1_val |= llcc_table[i].probe_target_ways << attr1_val |= llcc_table[i].probe_target_ways <<
...@@ -260,10 +259,12 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev) ...@@ -260,10 +259,12 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev)
attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK; attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK;
attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT; attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT;
ret = regmap_write(drv_data->regmap, attr1_cfg, attr1_val); ret = regmap_write(drv_data->bcast_regmap, attr1_cfg,
attr1_val);
if (ret) if (ret)
return ret; return ret;
ret = regmap_write(drv_data->regmap, attr0_cfg, attr0_val); ret = regmap_write(drv_data->bcast_regmap, attr0_cfg,
attr0_val);
if (ret) if (ret)
return ret; return ret;
if (llcc_table[i].activate_on_init) { if (llcc_table[i].activate_on_init) {
...@@ -279,24 +280,36 @@ int qcom_llcc_probe(struct platform_device *pdev, ...@@ -279,24 +280,36 @@ int qcom_llcc_probe(struct platform_device *pdev,
{ {
u32 num_banks; u32 num_banks;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct resource *res; struct resource *llcc_banks_res, *llcc_bcast_res;
void __iomem *base; void __iomem *llcc_banks_base, *llcc_bcast_base;
int ret, i; int ret, i;
drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
if (!drv_data) if (!drv_data)
return -ENOMEM; return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
base = devm_ioremap_resource(&pdev->dev, res); "llcc_base");
if (IS_ERR(base)) llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res);
return PTR_ERR(base); if (IS_ERR(llcc_banks_base))
return PTR_ERR(llcc_banks_base);
drv_data->regmap = devm_regmap_init_mmio(dev, base, drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base,
&llcc_regmap_config); &llcc_regmap_config);
if (IS_ERR(drv_data->regmap)) if (IS_ERR(drv_data->regmap))
return PTR_ERR(drv_data->regmap); return PTR_ERR(drv_data->regmap);
llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"llcc_broadcast_base");
llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res);
if (IS_ERR(llcc_bcast_base))
return PTR_ERR(llcc_bcast_base);
drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base,
&llcc_regmap_config);
if (IS_ERR(drv_data->bcast_regmap))
return PTR_ERR(drv_data->bcast_regmap);
ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0,
&num_banks); &num_banks);
if (ret) if (ret)
...@@ -318,8 +331,6 @@ int qcom_llcc_probe(struct platform_device *pdev, ...@@ -318,8 +331,6 @@ int qcom_llcc_probe(struct platform_device *pdev,
for (i = 0; i < num_banks; i++) for (i = 0; i < num_banks; i++)
drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
drv_data->bcast_off = num_banks * BANK_OFFSET_STRIDE;
drv_data->bitmap = devm_kcalloc(dev, drv_data->bitmap = devm_kcalloc(dev,
BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long),
GFP_KERNEL); GFP_KERNEL);
......
...@@ -70,22 +70,22 @@ struct llcc_slice_config { ...@@ -70,22 +70,22 @@ struct llcc_slice_config {
/** /**
* llcc_drv_data - Data associated with the llcc driver * llcc_drv_data - Data associated with the llcc driver
* @regmap: regmap associated with the llcc device * @regmap: regmap associated with the llcc device
* @bcast_regmap: regmap associated with llcc broadcast offset
* @cfg: pointer to the data structure for slice configuration * @cfg: pointer to the data structure for slice configuration
* @lock: mutex associated with each slice * @lock: mutex associated with each slice
* @cfg_size: size of the config data table * @cfg_size: size of the config data table
* @max_slices: max slices as read from device tree * @max_slices: max slices as read from device tree
* @bcast_off: Offset of the broadcast bank
* @num_banks: Number of llcc banks * @num_banks: Number of llcc banks
* @bitmap: Bit map to track the active slice ids * @bitmap: Bit map to track the active slice ids
* @offsets: Pointer to the bank offsets array * @offsets: Pointer to the bank offsets array
*/ */
struct llcc_drv_data { struct llcc_drv_data {
struct regmap *regmap; struct regmap *regmap;
struct regmap *bcast_regmap;
const struct llcc_slice_config *cfg; const struct llcc_slice_config *cfg;
struct mutex lock; struct mutex lock;
u32 cfg_size; u32 cfg_size;
u32 max_slices; u32 max_slices;
u32 bcast_off;
u32 num_banks; u32 num_banks;
unsigned long *bitmap; unsigned long *bitmap;
u32 *offsets; u32 *offsets;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment