cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

w1_ds2406.c (3366B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * w1_ds2406.c - w1 family 12 (DS2406) driver
      4 * based on w1_ds2413.c by Mariusz Bialonczyk <manio@skyboo.net>
      5 *
      6 * Copyright (c) 2014 Scott Alfter <scott@alfter.us>
      7 */
      8
      9#include <linux/kernel.h>
     10#include <linux/module.h>
     11#include <linux/moduleparam.h>
     12#include <linux/device.h>
     13#include <linux/types.h>
     14#include <linux/delay.h>
     15#include <linux/slab.h>
     16#include <linux/crc16.h>
     17
     18#include <linux/w1.h>
     19
     20#define W1_FAMILY_DS2406	0x12
     21
     22#define W1_F12_FUNC_READ_STATUS		   0xAA
     23#define W1_F12_FUNC_WRITE_STATUS	   0x55
     24
     25static ssize_t w1_f12_read_state(
     26	struct file *filp, struct kobject *kobj,
     27	struct bin_attribute *bin_attr,
     28	char *buf, loff_t off, size_t count)
     29{
     30	u8 w1_buf[6]={W1_F12_FUNC_READ_STATUS, 7, 0, 0, 0, 0};
     31	struct w1_slave *sl = kobj_to_w1_slave(kobj);
     32	u16 crc=0;
     33	int i;
     34	ssize_t rtnval=1;
     35
     36	if (off != 0)
     37		return 0;
     38	if (!buf)
     39		return -EINVAL;
     40
     41	mutex_lock(&sl->master->bus_mutex);
     42
     43	if (w1_reset_select_slave(sl)) {
     44		mutex_unlock(&sl->master->bus_mutex);
     45		return -EIO;
     46	}
     47
     48	w1_write_block(sl->master, w1_buf, 3);
     49	w1_read_block(sl->master, w1_buf+3, 3);
     50	for (i=0; i<6; i++)
     51		crc=crc16_byte(crc, w1_buf[i]);
     52	if (crc==0xb001) /* good read? */
     53		*buf=((w1_buf[3]>>5)&3)|0x30;
     54	else
     55		rtnval=-EIO;
     56
     57	mutex_unlock(&sl->master->bus_mutex);
     58
     59	return rtnval;
     60}
     61
     62static ssize_t w1_f12_write_output(
     63	struct file *filp, struct kobject *kobj,
     64	struct bin_attribute *bin_attr,
     65	char *buf, loff_t off, size_t count)
     66{
     67	struct w1_slave *sl = kobj_to_w1_slave(kobj);
     68	u8 w1_buf[6]={W1_F12_FUNC_WRITE_STATUS, 7, 0, 0, 0, 0};
     69	u16 crc=0;
     70	int i;
     71	ssize_t rtnval=1;
     72
     73	if (count != 1 || off != 0)
     74		return -EFAULT;
     75
     76	mutex_lock(&sl->master->bus_mutex);
     77
     78	if (w1_reset_select_slave(sl)) {
     79		mutex_unlock(&sl->master->bus_mutex);
     80		return -EIO;
     81	}
     82
     83	w1_buf[3] = (((*buf)&3)<<5)|0x1F;
     84	w1_write_block(sl->master, w1_buf, 4);
     85	w1_read_block(sl->master, w1_buf+4, 2);
     86	for (i=0; i<6; i++)
     87		crc=crc16_byte(crc, w1_buf[i]);
     88	if (crc==0xb001) /* good read? */
     89		w1_write_8(sl->master, 0xFF);
     90	else
     91		rtnval=-EIO;
     92
     93	mutex_unlock(&sl->master->bus_mutex);
     94	return rtnval;
     95}
     96
     97#define NB_SYSFS_BIN_FILES 2
     98static struct bin_attribute w1_f12_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
     99	{
    100		.attr = {
    101			.name = "state",
    102			.mode = S_IRUGO,
    103		},
    104		.size = 1,
    105		.read = w1_f12_read_state,
    106	},
    107	{
    108		.attr = {
    109			.name = "output",
    110			.mode = S_IRUGO | S_IWUSR | S_IWGRP,
    111		},
    112		.size = 1,
    113		.write = w1_f12_write_output,
    114	}
    115};
    116
    117static int w1_f12_add_slave(struct w1_slave *sl)
    118{
    119	int err = 0;
    120	int i;
    121
    122	for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
    123		err = sysfs_create_bin_file(
    124			&sl->dev.kobj,
    125			&(w1_f12_sysfs_bin_files[i]));
    126	if (err)
    127		while (--i >= 0)
    128			sysfs_remove_bin_file(&sl->dev.kobj,
    129				&(w1_f12_sysfs_bin_files[i]));
    130	return err;
    131}
    132
    133static void w1_f12_remove_slave(struct w1_slave *sl)
    134{
    135	int i;
    136	for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
    137		sysfs_remove_bin_file(&sl->dev.kobj,
    138			&(w1_f12_sysfs_bin_files[i]));
    139}
    140
    141static const struct w1_family_ops w1_f12_fops = {
    142	.add_slave      = w1_f12_add_slave,
    143	.remove_slave   = w1_f12_remove_slave,
    144};
    145
    146static struct w1_family w1_family_12 = {
    147	.fid = W1_FAMILY_DS2406,
    148	.fops = &w1_f12_fops,
    149};
    150module_w1_family(w1_family_12);
    151
    152MODULE_AUTHOR("Scott Alfter <scott@alfter.us>");
    153MODULE_DESCRIPTION("w1 family 12 driver for DS2406 2 Pin IO");
    154MODULE_LICENSE("GPL");