aboutsummaryrefslogtreecommitdiff
path: root/drivers/platform/x86/amd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/amd')
-rw-r--r--drivers/platform/x86/amd/hsmp.c74
1 files changed, 52 insertions, 22 deletions
diff --git a/drivers/platform/x86/amd/hsmp.c b/drivers/platform/x86/amd/hsmp.c
index e3354683b138..287eaa9b0dda 100644
--- a/drivers/platform/x86/amd/hsmp.c
+++ b/drivers/platform/x86/amd/hsmp.c
@@ -40,9 +40,10 @@
* register into the SMN_INDEX register, and reads/writes the SMN_DATA reg.
* Below are required SMN address for HSMP Mailbox register offsets in SMU address space
*/
-#define SMN_HSMP_MSG_ID 0x3B10534
-#define SMN_HSMP_MSG_RESP 0x3B10980
-#define SMN_HSMP_MSG_DATA 0x3B109E0
+#define SMN_HSMP_BASE 0x3B00000
+#define SMN_HSMP_MSG_ID 0x0010534
+#define SMN_HSMP_MSG_RESP 0x0010980
+#define SMN_HSMP_MSG_DATA 0x00109E0
#define HSMP_INDEX_REG 0xc4
#define HSMP_DATA_REG 0xc8
@@ -53,8 +54,17 @@
#define HSMP_ATTR_GRP_NAME_SIZE 10
+struct hsmp_mbaddr_info {
+ u32 base_addr;
+ u32 msg_id_off;
+ u32 msg_resp_off;
+ u32 msg_arg_off;
+ u32 size;
+};
+
struct hsmp_socket {
struct bin_attribute hsmp_attr;
+ struct hsmp_mbaddr_info mbinfo;
void __iomem *metric_tbl_addr;
struct semaphore hsmp_sem;
char name[HSMP_ATTR_GRP_NAME_SIZE];
@@ -72,7 +82,7 @@ struct hsmp_plat_device {
static struct hsmp_plat_device plat_dev;
-static int amd_hsmp_rdwr(struct hsmp_socket *sock, u32 address,
+static int amd_hsmp_rdwr(struct hsmp_socket *sock, u32 offset,
u32 *value, bool write)
{
int ret;
@@ -80,7 +90,8 @@ static int amd_hsmp_rdwr(struct hsmp_socket *sock, u32 address,
if (!sock->root)
return -ENODEV;
- ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG, address);
+ ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG,
+ sock->mbinfo.base_addr + offset);
if (ret)
return ret;
@@ -101,14 +112,17 @@ static int amd_hsmp_rdwr(struct hsmp_socket *sock, u32 address,
*/
static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *msg)
{
+ struct hsmp_mbaddr_info *mbinfo;
unsigned long timeout, short_sleep;
u32 mbox_status;
u32 index;
int ret;
+ mbinfo = &sock->mbinfo;
+
/* Clear the status register */
mbox_status = HSMP_STATUS_NOT_READY;
- ret = amd_hsmp_rdwr(sock, SMN_HSMP_MSG_RESP, &mbox_status, HSMP_WR);
+ ret = amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_WR);
if (ret) {
pr_err("Error %d clearing mailbox status register\n", ret);
return ret;
@@ -117,7 +131,7 @@ static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *ms
index = 0;
/* Write any message arguments */
while (index < msg->num_args) {
- ret = amd_hsmp_rdwr(sock, SMN_HSMP_MSG_DATA + (index << 2),
+ ret = amd_hsmp_rdwr(sock, mbinfo->msg_arg_off + (index << 2),
&msg->args[index], HSMP_WR);
if (ret) {
pr_err("Error %d writing message argument %d\n", ret, index);
@@ -127,7 +141,7 @@ static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *ms
}
/* Write the message ID which starts the operation */
- ret = amd_hsmp_rdwr(sock, SMN_HSMP_MSG_ID, &msg->msg_id, HSMP_WR);
+ ret = amd_hsmp_rdwr(sock, mbinfo->msg_id_off, &msg->msg_id, HSMP_WR);
if (ret) {
pr_err("Error %d writing message ID %u\n", ret, msg->msg_id);
return ret;
@@ -144,7 +158,7 @@ static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *ms
timeout = jiffies + msecs_to_jiffies(HSMP_MSG_TIMEOUT);
while (time_before(jiffies, timeout)) {
- ret = amd_hsmp_rdwr(sock, SMN_HSMP_MSG_RESP, &mbox_status, HSMP_RD);
+ ret = amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_RD);
if (ret) {
pr_err("Error %d reading mailbox status\n", ret);
return ret;
@@ -179,7 +193,7 @@ static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *ms
*/
index = 0;
while (index < msg->response_sz) {
- ret = amd_hsmp_rdwr(sock, SMN_HSMP_MSG_DATA + (index << 2),
+ ret = amd_hsmp_rdwr(sock, mbinfo->msg_arg_off + (index << 2),
&msg->args[index], HSMP_RD);
if (ret) {
pr_err("Error %d reading response %u for message ID:%u\n",
@@ -487,24 +501,22 @@ static int hsmp_cache_proto_ver(void)
return ret;
}
-static int hsmp_pltdrv_probe(struct platform_device *pdev)
+static int init_platform_device(void)
{
+ struct hsmp_socket *sock;
int ret, i;
- plat_dev.sock = devm_kzalloc(&pdev->dev,
- (plat_dev.num_sockets * sizeof(struct hsmp_socket)),
- GFP_KERNEL);
- if (!plat_dev.sock)
- return -ENOMEM;
- plat_dev.dev = &pdev->dev;
-
for (i = 0; i < plat_dev.num_sockets; i++) {
- sema_init(&plat_dev.sock[i].hsmp_sem, 1);
- plat_dev.sock[i].sock_ind = i;
-
if (!node_to_amd_nb(i))
return -ENODEV;
- plat_dev.sock[i].root = node_to_amd_nb(i)->root;
+ sock = &plat_dev.sock[i];
+ sock->root = node_to_amd_nb(i)->root;
+ sock->sock_ind = i;
+ sock->mbinfo.base_addr = SMN_HSMP_BASE;
+ sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID;
+ sock->mbinfo.msg_resp_off = SMN_HSMP_MSG_RESP;
+ sock->mbinfo.msg_arg_off = SMN_HSMP_MSG_DATA;
+ sema_init(&sock->hsmp_sem, 1);
/* Test the hsmp interface on each socket */
ret = hsmp_test(i, 0xDEADBEEF);
@@ -516,6 +528,24 @@ static int hsmp_pltdrv_probe(struct platform_device *pdev)
}
}
+ return 0;
+}
+
+static int hsmp_pltdrv_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ plat_dev.sock = devm_kzalloc(&pdev->dev,
+ (plat_dev.num_sockets * sizeof(struct hsmp_socket)),
+ GFP_KERNEL);
+ if (!plat_dev.sock)
+ return -ENOMEM;
+ plat_dev.dev = &pdev->dev;
+
+ ret = init_platform_device();
+ if (ret)
+ return ret;
+
plat_dev.hsmp_device.name = HSMP_CDEV_NAME;
plat_dev.hsmp_device.minor = MISC_DYNAMIC_MINOR;
plat_dev.hsmp_device.fops = &hsmp_fops;