brintos

brintos / linux-shallow public Read only

0
0
Text · 3.3 KiB · 4676f06 Raw
139 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * AMD MP2 1.1 communication interfaces4 *5 * Copyright (c) 2022, Advanced Micro Devices, Inc.6 * All Rights Reserved.7 *8 * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>9 */10#include <linux/amd-pmf-io.h>11#include <linux/io-64-nonatomic-lo-hi.h>12#include <linux/iopoll.h>13 14#include "amd_sfh_interface.h"15 16static struct amd_mp2_dev *emp2;17 18static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)19{20	struct sfh_cmd_response cmd_resp;21 22	/* Get response with status within a max of 10000 ms timeout */23	if (!readl_poll_timeout(mp2->mmio + amd_get_p2c_val(mp2, 0), cmd_resp.resp,24				(cmd_resp.response.response == 0 &&25				cmd_resp.response.cmd_id == cmd_id && (sid == 0xff ||26				cmd_resp.response.sensor_id == sid)), 500, 10000000))27		return cmd_resp.response.response;28 29	return -1;30}31 32static void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)33{34	struct sfh_cmd_base cmd_base;35 36	cmd_base.ul = 0;37	cmd_base.cmd.cmd_id = ENABLE_SENSOR;38	cmd_base.cmd.intr_disable = 0;39	cmd_base.cmd.sub_cmd_value = 1;40	cmd_base.cmd.sensor_id = info.sensor_idx;41 42	writel(cmd_base.ul, privdata->mmio + amd_get_c2p_val(privdata, 0));43}44 45static void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)46{47	struct sfh_cmd_base cmd_base;48 49	cmd_base.ul = 0;50	cmd_base.cmd.cmd_id = DISABLE_SENSOR;51	cmd_base.cmd.intr_disable = 0;52	cmd_base.cmd.sub_cmd_value = 1;53	cmd_base.cmd.sensor_id = sensor_idx;54 55	writeq(0x0, privdata->mmio + amd_get_c2p_val(privdata, 1));56	writel(cmd_base.ul, privdata->mmio + amd_get_c2p_val(privdata, 0));57}58 59static void amd_stop_all_sensor(struct amd_mp2_dev *privdata)60{61	struct sfh_cmd_base cmd_base;62 63	cmd_base.ul = 0;64	cmd_base.cmd.cmd_id = DISABLE_SENSOR;65	cmd_base.cmd.intr_disable = 0;66	/* 0xf indicates all sensors */67	cmd_base.cmd.sensor_id = 0xf;68 69	writel(cmd_base.ul, privdata->mmio + amd_get_c2p_val(privdata, 0));70}71 72static struct amd_mp2_ops amd_sfh_ops = {73	.start = amd_start_sensor,74	.stop = amd_stop_sensor,75	.stop_all = amd_stop_all_sensor,76	.response = amd_sfh_wait_response,77};78 79void sfh_deinit_emp2(void)80{81	emp2 = NULL;82}83 84void sfh_interface_init(struct amd_mp2_dev *mp2)85{86	mp2->mp2_ops = &amd_sfh_ops;87	emp2 = mp2;88}89 90static int amd_sfh_hpd_info(u8 *user_present)91{92	struct hpd_status hpdstatus;93 94	if (!user_present)95		return -EINVAL;96 97	if (!emp2 || !emp2->dev_en.is_hpd_present)98		return -ENODEV;99 100	hpdstatus.val = readl(emp2->mmio + amd_get_c2p_val(emp2, 4));101	*user_present = hpdstatus.shpd.presence;102 103	return 0;104}105 106static int amd_sfh_als_info(u32 *ambient_light)107{108	struct sfh_als_data als_data;109	void __iomem *sensoraddr;110 111	if (!ambient_light)112		return -EINVAL;113 114	if (!emp2 || !emp2->dev_en.is_als_present)115		return -ENODEV;116 117	sensoraddr = emp2->vsbase +118		(ALS_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +119		OFFSET_SENSOR_DATA_DEFAULT;120	memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));121	*ambient_light = amd_sfh_float_to_int(als_data.lux);122 123	return 0;124}125 126int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)127{128	if (sfh_info) {129		switch (op) {130		case MT_HPD:131			return amd_sfh_hpd_info(&sfh_info->user_present);132		case MT_ALS:133			return amd_sfh_als_info(&sfh_info->ambient_light);134		}135	}136	return -EINVAL;137}138EXPORT_SYMBOL_GPL(amd_get_sfh_info);139