Linux Audio

Check our new training course

Yocto / OpenEmbedded training

Feb 10-13, 2025
Register
Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
  4 *
  5 * Original author:
  6 * Ben Collins <bcollins@ubuntu.com>
  7 *
  8 * Additional work by:
  9 * John Brooks <john.brooks@bluecherry.net>
 10 */
 11
 12#include <linux/kernel.h>
 13#include <linux/delay.h>
 14
 15#include "solo6x10.h"
 16
 17/* Control */
 18#define EE_SHIFT_CLK	0x04
 19#define EE_CS		0x08
 20#define EE_DATA_WRITE	0x02
 21#define EE_DATA_READ	0x01
 22#define EE_ENB		(0x80 | EE_CS)
 23
 24#define eeprom_delay()	udelay(100)
 25#if 0
 26#define eeprom_delay()	solo_reg_read(solo_dev, SOLO_EEPROM_CTRL)
 27#define eeprom_delay()	({				\
 28	int i, ret;					\
 29	udelay(100);					\
 30	for (i = ret = 0; i < 1000 && !ret; i++)	\
 31		ret = solo_eeprom_reg_read(solo_dev);	\
 32})
 33#endif
 34#define ADDR_LEN	6
 35
 36/* Commands */
 37#define EE_EWEN_CMD	4
 38#define EE_EWDS_CMD	4
 39#define EE_WRITE_CMD	5
 40#define EE_READ_CMD	6
 41#define EE_ERASE_CMD	7
 42
 43static unsigned int solo_eeprom_reg_read(struct solo_dev *solo_dev)
 44{
 45	return solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) & EE_DATA_READ;
 46}
 47
 48static void solo_eeprom_reg_write(struct solo_dev *solo_dev, u32 data)
 49{
 50	solo_reg_write(solo_dev, SOLO_EEPROM_CTRL, data);
 51	eeprom_delay();
 52}
 53
 54static void solo_eeprom_cmd(struct solo_dev *solo_dev, int cmd)
 55{
 56	int i;
 57
 58	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ACCESS_EN);
 59	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
 60
 61	for (i = 4 + ADDR_LEN; i >= 0; i--) {
 62		int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
 63
 64		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | dataval);
 65		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
 66				      EE_SHIFT_CLK | dataval);
 67	}
 68
 69	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
 70}
 71
 72unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en)
 73{
 74	int ewen_cmd = (w_en ? 0x3f : 0) | (EE_EWEN_CMD << ADDR_LEN);
 75	unsigned int retval = 0;
 76	int i;
 77
 78	solo_eeprom_cmd(solo_dev, ewen_cmd);
 79
 80	for (i = 0; i < 16; i++) {
 81		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
 82				      EE_SHIFT_CLK);
 83		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
 84		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
 85		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
 86	}
 87
 88	solo_eeprom_reg_write(solo_dev, ~EE_CS);
 89	retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
 90
 91	return retval;
 92}
 93
 94__be16 solo_eeprom_read(struct solo_dev *solo_dev, int loc)
 95{
 96	int read_cmd = loc | (EE_READ_CMD << ADDR_LEN);
 97	u16 retval = 0;
 98	int i;
 99
100	solo_eeprom_cmd(solo_dev, read_cmd);
101
102	for (i = 0; i < 16; i++) {
103		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
104				      EE_SHIFT_CLK);
105		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
106		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
107	}
108
109	solo_eeprom_reg_write(solo_dev, ~EE_CS);
110
111	return (__force __be16)retval;
112}
113
114int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
115		      __be16 data)
116{
117	int write_cmd = loc | (EE_WRITE_CMD << ADDR_LEN);
118	unsigned int retval;
119	int i;
120
121	solo_eeprom_cmd(solo_dev, write_cmd);
122
123	for (i = 15; i >= 0; i--) {
124		unsigned int dataval = ((__force unsigned)data >> i) & 1;
125
126		solo_eeprom_reg_write(solo_dev, EE_ENB);
127		solo_eeprom_reg_write(solo_dev,
128				      EE_ENB | (dataval << 1) | EE_SHIFT_CLK);
129	}
130
131	solo_eeprom_reg_write(solo_dev, EE_ENB);
132	solo_eeprom_reg_write(solo_dev, ~EE_CS);
133	solo_eeprom_reg_write(solo_dev, EE_ENB);
134
135	for (i = retval = 0; i < 10000 && !retval; i++)
136		retval = solo_eeprom_reg_read(solo_dev);
137
138	solo_eeprom_reg_write(solo_dev, ~EE_CS);
139
140	return !retval;
141}