blob: 1abfa96483e0898a1a5a08b27a0b76ea5dad0cf4 [file] [log] [blame]
/* Copyright (c) 2011-2017, 2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _ARCH_ARM_MACH_MSM_BUS_CORE_H
#define _ARCH_ARM_MACH_MSM_BUS_CORE_H
#include <linux/types.h>
#include <linux/device.h>
#include <linux/radix-tree.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/msm-bus-board.h>
#include <linux/msm-bus.h>
#define MSM_BUS_DBG(msg, ...) \
pr_debug(msg, ## __VA_ARGS__)
#define MSM_BUS_ERR(msg, ...) \
pr_err(msg, ## __VA_ARGS__)
#define MSM_BUS_WARN(msg, ...) \
pr_warn(msg, ## __VA_ARGS__)
#define MSM_FAB_ERR(msg, ...) \
dev_err(&fabric->fabdev.dev, msg, ## __VA_ARGS__)
#define IS_MASTER_VALID(mas) \
(((mas >= MSM_BUS_MASTER_FIRST) && (mas <= MSM_BUS_MASTER_LAST)) \
? 1 : 0)
#define IS_SLAVE_VALID(slv) \
(((slv >= MSM_BUS_SLAVE_FIRST) && (slv <= MSM_BUS_SLAVE_LAST)) ? 1 : 0)
#define INTERLEAVED_BW(fab_pdata, bw, ports) \
((fab_pdata->il_flag) ? ((bw < 0) \
? -msm_bus_div64((ports), (-bw)) : msm_bus_div64((ports), (bw))) : (bw))
#define INTERLEAVED_VAL(fab_pdata, n) \
((fab_pdata->il_flag) ? (n) : 1)
#define KBTOB(a) (a * 1000ULL)
#define MAX_REG_NAME (50)
enum msm_bus_dbg_op_type {
MSM_BUS_DBG_UNREGISTER = -2,
MSM_BUS_DBG_REGISTER,
MSM_BUS_DBG_OP = 1,
};
enum msm_bus_hw_sel {
MSM_BUS_RPM = 0,
MSM_BUS_NOC,
MSM_BUS_BIMC,
MSM_BUS_QNOC,
};
struct msm_bus_arb_ops {
uint32_t (*register_client)(struct msm_bus_scale_pdata *pdata);
int (*update_request)(uint32_t cl, unsigned int index);
int (*update_context)(uint32_t cl, bool active_only,
unsigned int ctx_idx);
void (*unregister_client)(uint32_t cl);
struct msm_bus_client_handle*
(*register_cl)(uint32_t mas, uint32_t slv, char *name,
bool active_only);
int (*update_bw)(struct msm_bus_client_handle *cl, u64 ab, u64 ib);
void (*unregister)(struct msm_bus_client_handle *cl);
int (*update_bw_context)(struct msm_bus_client_handle *cl, u64 act_ab,
u64 act_ib, u64 dual_ib, u64 dual_ab);
int (*query_usecase)(struct msm_bus_tcs_usecase *tcs_usecase,
uint32_t cl, unsigned int index);
int (*query_usecase_all)(struct msm_bus_tcs_handle *tcs_handle,
uint32_t cl);
};
enum {
SLAVE_NODE,
MASTER_NODE,
CLK_NODE,
NR_LIM_NODE,
};
extern struct bus_type msm_bus_type;
extern struct msm_bus_arb_ops arb_ops;
extern void msm_bus_arb_setops_legacy(struct msm_bus_arb_ops *arb_ops);
struct msm_bus_node_info {
unsigned int id;
unsigned int priv_id;
unsigned int mas_hw_id;
unsigned int slv_hw_id;
int gateway;
int *masterp;
int *qport;
int num_mports;
int *slavep;
int num_sports;
int *tier;
int num_tiers;
int ahb;
int hw_sel;
const char *slaveclk[NUM_CTX];
const char *memclk[NUM_CTX];
const char *iface_clk_node;
unsigned int buswidth;
unsigned int ws;
unsigned int mode;
unsigned int perm_mode;
unsigned int prio_lvl;
unsigned int prio_rd;
unsigned int prio_wr;
unsigned int prio1;
unsigned int prio0;
unsigned int num_thresh;
u64 *th;
u64 cur_lim_bw;
unsigned int mode_thresh;
bool dual_conf;
u64 *bimc_bw;
bool nr_lim;
u32 ff;
bool rt_mas;
u32 bimc_gp;
u32 bimc_thmp;
u64 floor_bw;
const char *name;
};
struct path_node {
uint64_t clk[NUM_CTX];
uint64_t bw[NUM_CTX];
uint64_t *sel_clk;
uint64_t *sel_bw;
int next;
};
struct msm_bus_link_info {
uint64_t clk[NUM_CTX];
uint64_t *sel_clk;
uint64_t memclk;
int64_t bw[NUM_CTX];
int64_t *sel_bw;
int *tier;
int num_tiers;
};
struct nodeclk {
struct clk *clk;
struct regulator *reg;
uint64_t rate;
bool dirty;
bool enable_only_clk;
bool setrate_only_clk;
bool enable;
char reg_name[MAX_REG_NAME];
};
struct msm_bus_inode_info {
struct msm_bus_node_info *node_info;
uint64_t max_bw;
uint64_t max_clk;
uint64_t cur_lim_bw;
uint64_t cur_prg_bw;
struct msm_bus_link_info link_info;
int num_pnodes;
struct path_node *pnode;
int commit_index;
struct nodeclk nodeclk[NUM_CTX];
struct nodeclk memclk[NUM_CTX];
struct nodeclk iface_clk;
void *hw_data;
};
struct msm_bus_node_hw_info {
bool dirty;
unsigned int hw_id;
uint64_t bw;
};
struct msm_bus_hw_algorithm {
int (*allocate_commit_data)(struct msm_bus_fabric_registration
*fab_pdata, void **cdata, int ctx);
void *(*allocate_hw_data)(struct platform_device *pdev,
struct msm_bus_fabric_registration *fab_pdata);
void (*node_init)(void *hw_data, struct msm_bus_inode_info *info);
void (*free_commit_data)(void *cdata);
void (*update_bw)(struct msm_bus_inode_info *hop,
struct msm_bus_inode_info *info,
struct msm_bus_fabric_registration *fab_pdata,
void *sel_cdata, int *master_tiers,
int64_t add_bw);
void (*fill_cdata_buffer)(int *curr, char *buf, const int max_size,
void *cdata, int nmasters, int nslaves, int ntslaves);
int (*commit)(struct msm_bus_fabric_registration
*fab_pdata, void *hw_data, void **cdata);
int (*port_unhalt)(uint32_t haltid, uint8_t mport);
int (*port_halt)(uint32_t haltid, uint8_t mport);
void (*config_master)(struct msm_bus_fabric_registration *fab_pdata,
struct msm_bus_inode_info *info,
uint64_t req_clk, uint64_t req_bw);
void (*config_limiter)(struct msm_bus_fabric_registration *fab_pdata,
struct msm_bus_inode_info *info);
bool (*update_bw_reg)(int mode);
};
struct msm_bus_fabric_device {
int id;
const char *name;
struct device dev;
const struct msm_bus_fab_algorithm *algo;
const struct msm_bus_board_algorithm *board_algo;
struct msm_bus_hw_algorithm hw_algo;
int visited;
int num_nr_lim;
u64 nr_lim_thresh;
u32 eff_fact;
};
#define to_msm_bus_fabric_device(d) container_of(d, \
struct msm_bus_fabric_device, d)
struct msm_bus_fabric {
struct msm_bus_fabric_device fabdev;
int ahb;
void *cdata[NUM_CTX];
bool arb_dirty;
bool clk_dirty;
struct radix_tree_root fab_tree;
int num_nodes;
struct list_head gateways;
struct msm_bus_inode_info info;
struct msm_bus_fabric_registration *pdata;
void *hw_data;
};
#define to_msm_bus_fabric(d) container_of(d, \
struct msm_bus_fabric, d)
struct msm_bus_fab_algorithm {
int (*update_clks)(struct msm_bus_fabric_device *fabdev,
struct msm_bus_inode_info *pme, int index,
uint64_t curr_clk, uint64_t req_clk,
uint64_t bwsum, int flag, int ctx,
unsigned int cl_active_flag);
int (*port_halt)(struct msm_bus_fabric_device *fabdev, int portid);
int (*port_unhalt)(struct msm_bus_fabric_device *fabdev, int portid);
int (*commit)(struct msm_bus_fabric_device *fabdev);
struct msm_bus_inode_info *(*find_node)(struct msm_bus_fabric_device
*fabdev, int id);
struct msm_bus_inode_info *(*find_gw_node)(struct msm_bus_fabric_device
*fabdev, int id);
struct list_head *(*get_gw_list)(struct msm_bus_fabric_device *fabdev);
void (*update_bw)(struct msm_bus_fabric_device *fabdev, struct
msm_bus_inode_info * hop, struct msm_bus_inode_info *info,
int64_t add_bw, int *master_tiers, int ctx);
void (*config_master)(struct msm_bus_fabric_device *fabdev,
struct msm_bus_inode_info *info, uint64_t req_clk,
uint64_t req_bw);
void (*config_limiter)(struct msm_bus_fabric_device *fabdev,
struct msm_bus_inode_info *info);
};
struct msm_bus_board_algorithm {
int board_nfab;
void (*assign_iids)(struct msm_bus_fabric_registration *fabreg,
int fabid);
int (*get_iid)(int id);
};
/**
* Used to store the list of fabrics and other info to be
* maintained outside the fabric structure.
* Used while calculating path, and to find fabric ptrs
*/
struct msm_bus_fabnodeinfo {
struct list_head list;
struct msm_bus_inode_info *info;
};
struct msm_bus_client {
int id;
struct msm_bus_scale_pdata *pdata;
int *src_pnode;
int curr;
struct device **src_devs;
};
uint64_t msm_bus_div64(uint64_t num, unsigned int base);
int msm_bus_fabric_device_register(struct msm_bus_fabric_device *fabric);
void msm_bus_fabric_device_unregister(struct msm_bus_fabric_device *fabric);
struct msm_bus_fabric_device *msm_bus_get_fabric_device(int fabid);
int msm_bus_get_num_fab(void);
int msm_bus_hw_fab_init(struct msm_bus_fabric_registration *pdata,
struct msm_bus_hw_algorithm *hw_algo);
void msm_bus_board_init(struct msm_bus_fabric_registration *pdata);
#if defined(CONFIG_MSM_RPM_SMD)
int msm_bus_rpm_hw_init(struct msm_bus_fabric_registration *pdata,
struct msm_bus_hw_algorithm *hw_algo);
int msm_bus_remote_hw_commit(struct msm_bus_fabric_registration
*fab_pdata, void *hw_data, void **cdata);
void msm_bus_rpm_fill_cdata_buffer(int *curr, char *buf, const int max_size,
void *cdata, int nmasters, int nslaves, int ntslaves);
#else
static inline int msm_bus_rpm_hw_init(struct msm_bus_fabric_registration *pdata,
struct msm_bus_hw_algorithm *hw_algo)
{
return 0;
}
static inline int msm_bus_remote_hw_commit(struct msm_bus_fabric_registration
*fab_pdata, void *hw_data, void **cdata)
{
return 0;
}
static inline void msm_bus_rpm_fill_cdata_buffer(int *curr, char *buf,
const int max_size, void *cdata, int nmasters, int nslaves,
int ntslaves)
{
}
#endif
int msm_bus_noc_hw_init(struct msm_bus_fabric_registration *pdata,
struct msm_bus_hw_algorithm *hw_algo);
int msm_bus_bimc_hw_init(struct msm_bus_fabric_registration *pdata,
struct msm_bus_hw_algorithm *hw_algo);
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_QCOM_BUS_SCALING)
void msm_bus_dbg_client_data(struct msm_bus_scale_pdata *pdata, int index,
uint32_t cl);
void msm_bus_dbg_commit_data(const char *fabname, void *cdata,
int nmasters, int nslaves, int ntslaves, int op);
int msm_bus_dbg_add_client(const struct msm_bus_client_handle *pdata);
int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata,
u64 ab, u64 ib);
void msm_bus_dbg_remove_client(const struct msm_bus_client_handle *pdata);
#else
static inline void msm_bus_dbg_client_data(struct msm_bus_scale_pdata *pdata,
int index, uint32_t cl)
{
}
static inline void msm_bus_dbg_commit_data(const char *fabname,
void *cdata, int nmasters, int nslaves, int ntslaves,
int op)
{
}
static inline void msm_bus_dbg_remove_client
(const struct msm_bus_client_handle *pdata)
{
}
static inline int
msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata,
u64 ab, u64 ib)
{
return 0;
}
static inline int
msm_bus_dbg_add_client(const struct msm_bus_client_handle *pdata)
{
return 0;
}
#endif
#ifdef CONFIG_CORESIGHT
int msmbus_coresight_init(struct platform_device *pdev);
void msmbus_coresight_remove(struct platform_device *pdev);
int msmbus_coresight_init_adhoc(struct platform_device *pdev,
struct device_node *of_node);
void msmbus_coresight_remove_adhoc(struct platform_device *pdev);
#else
static inline int msmbus_coresight_init(struct platform_device *pdev)
{
return 0;
}
static inline void msmbus_coresight_remove(struct platform_device *pdev)
{
}
static inline int msmbus_coresight_init_adhoc(struct platform_device *pdev,
struct device_node *of_node)
{
return 0;
}
static inline void msmbus_coresight_remove_adhoc(struct platform_device *pdev)
{
}
#endif
#ifdef CONFIG_OF
void msm_bus_of_get_nfab(struct platform_device *pdev,
struct msm_bus_fabric_registration *pdata);
struct msm_bus_fabric_registration
*msm_bus_of_get_fab_data(struct platform_device *pdev);
static inline void msm_bus_board_set_nfab(struct msm_bus_fabric_registration
*pdata, int nfab)
{
}
#else
void msm_bus_board_set_nfab(struct msm_bus_fabric_registration *pdata,
int nfab);
static inline void msm_bus_of_get_nfab(struct platform_device *pdev,
struct msm_bus_fabric_registration *pdata)
{
}
static inline struct msm_bus_fabric_registration
*msm_bus_of_get_fab_data(struct platform_device *pdev)
{
return NULL;
}
#endif
#endif /*_ARCH_ARM_MACH_MSM_BUS_CORE_H*/